• Domingo 22 de Diciembre de 2024, 18:31

Autor Tema:  Problema de Byte NULL con archivos  (Leído 2287 veces)

Rombus

  • Miembro MUY activo
  • ***
  • Mensajes: 105
  • Nacionalidad: ar
    • Ver Perfil
    • http://myspace.com/punkrecycle
Problema de Byte NULL con archivos
« en: Martes 16 de Septiembre de 2008, 03:13 »
0
Hola gente!

tengo un problema al intentar practicamente duplicar un archivo donde se cumpla una condicion, si la line del archivo es una directiva, y mas especificamente si es un include <...>.

Intento hacer un programa que posea un preset para acomodar todos los codigos fuente que me pasen o que baje de internet a mi gusto, indentados, posicion de llaves, orden, etc...

pero mi problema es que en la "duplicacion" cuando intento abrir el archivo duplicado me tira un error diciendome que en el archivo hay un byte NULL y que se abrio solo lectura.



abro el archivo en un editor Hexadecimal y efectivamente hay un byte null. (totalmente involuntario)

este es mi codigo:

Código: Text
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4.  
  5. #define PATH "/home/rombus/Escritorio/sample.c"
  6. #define TERMINADO "/home/rombus/Escritorio/prueba.c"
  7.  
  8. #define FALSE 0
  9. #define TRUE !FALSE
  10.  
  11. #define INCLUDE 1
  12. #define DEFINE  2
  13. #define UNKNOWN -1
  14.  
  15. #define STD     3
  16. #define LOCAL   4
  17.  
  18. #define hastaEOL(a)             while((fgetc(a)!= 'n') && (fgetc(a)  != EOF))
  19. #define unoParaAtraz(a)         fseek(a,(long)-1,SEEK_CUR)
  20. #define dosParaAtraz(a)         fseek(a,(long)-2,SEEK_CUR)
  21. #define unoParaAdelante(a)      fseek(a,(long)1,SEEK_CUR)
  22. #define dosParaAdelnate(a)      fseek(a,(long)2,SEEK_CUR)
  23.  
  24. typedef char boolean;
  25. typedef char macroType;
  26.  
  27. ///-Prototypes-///
  28. char *getLine(FILE *a);
  29. macroType define_o_include(FILE *a);
  30. macroType std_o_local(FILE *a);
  31. boolean esMacro(FILE *a);
  32. void comeBlancos(FILE *a);
  33. boolean saltoMacros(FILE *a);
  34.  
  35. void pasaIncludesStd(FILE *a, FILE *b, boolean *flagLocal){
  36.     long pos, inicio = ftell(a),len;
  37.     char c; //Variable de control
  38.     char *cadena = (char *)malloc(sizeof(char)*255);
  39.     macroType control;
  40.    
  41.     while(esMacro(a)){
  42.         pos = (ftell(a));      
  43.         control = define_o_include(a);
  44.         if(control == INCLUDE){
  45.             c = std_o_local(a);
  46.             if(c == STD){
  47.                 hastaEOL(a);        //Me paro al final de la linea
  48.                 len = ftell(a)-pos; //Me da la cantidad de bytes q se corrio del principio
  49.                 fseek(a,(long)pos,SEEK_SET);
  50.                 cadena = getLine(a);
  51.                 fwrite(cadena,sizeof(char),len,b);  //Tener cuidado con esto, posible nido de bugs
  52.                 printf("escribio: %s - n",cadena);
  53.             }
  54.             else if(c == LOCAL)
  55.                 (*flagLocal) = TRUE;
  56.         }
  57.         else if(control == DEFINE)  //Si es un define salto toda la linea
  58.             hastaEOL(a);       
  59.     }
  60.     fseek(a,inicio*-1,SEEK_CUR);    //Voy a donde estaba cuando me lo pasaron
  61. }
  62.  
  63. int main(void){
  64.     FILE *a = fopen(PATH,"rb");
  65.     FILE *b = fopen(TERMINADO,"wt");
  66.     boolean flagLocal = FALSE;
  67.    
  68.     pasaIncludesStd(a,b,&flagLocal);    //pasar los includes <> 
  69.    
  70.     fclose(a);
  71.     fclose(b);
  72.     return 0;
  73. }
  74.  
  75. ///-FUNCIONES-///
  76. char *getLine(FILE *a){
  77.     char *l = (char*)malloc(255*sizeof(char));
  78.     int i = 0;
  79.    
  80.     do{
  81.         l[i] = fgetc(a);
  82.     }while((l[i] != 'n') && (l[i++] != EOF));
  83.     return l;
  84. }
  85. macroType define_o_include(FILE *a){
  86.     char c =fgetc(a);
  87.    
  88.     if(c == '#')        //Por si cuando invocan la funcion no saben si es macro
  89.         c = fgetc(a);
  90.        
  91.     if(c == 'i')
  92.         return INCLUDE;
  93.     if(c == 'd')
  94.         return DEFINE;
  95.     return UNKNOWN;
  96. }
  97. macroType std_o_local(FILE *a){
  98. #define LEN_INCLUDE 8   //Largo de la palabra "#include "
  99.     int i=0;
  100.     char c = fgetc(a);
  101.        
  102.     if(c == '#')            //Si llamo a la funcion sin antes haber leido el '#'
  103.         unoParaAtraz(a);
  104.     else                    //Si llamo a la funcion antes habiendo leido el '#'
  105.         dosParaAtraz(a);
  106.        
  107.     while(i++<LEN_INCLUDE)  //Salto el "#include "
  108.         fgetc(a);
  109.        
  110.     c = fgetc(a);   //Leo el "" o el <>
  111.     printf("el caracter es: %cn",c);
  112.    
  113.     if(c == '"')
  114.         return LOCAL;
  115.     else if(c == '<')
  116.         return STD;
  117.     return UNKNOWN;
  118. }
  119. boolean esMacro(FILE *a){
  120.     char c; 
  121.    
  122.     comeBlancos(a);
  123.     c = fgetc(a);
  124.     unoParaAtraz(a);
  125.     if(c == '#')
  126.         return TRUE;   
  127.     return FALSE;
  128. }
  129. void comeBlancos(FILE *a){
  130.     char b;
  131.    
  132.     while( (b = fgetc(a)) == ' ' || b == 'n' || b == 't');
  133.     printf("salio del comeBlancos con un %cn",b);
  134.     unoParaAtraz(a);
  135. }
  136. boolean saltoMacros(FILE *a){
  137.     char c;
  138.     boolean flag = FALSE;
  139.    
  140.     do{
  141.         if(flag)            //Leo toda la linea una vez que leyo el primer caracter
  142.             hastaEOL(a);
  143.         else
  144.             flag = TRUE;    //Cuando es la primera vez habilito la bandera
  145.            
  146.         comeBlancos(a);
  147.         c = fgetc(a);
  148.     }while(c =='#');
  149.     unoParaAtraz(a);
  150.     return FALSE;   //Terminaron los macros
  151. }
  152.  


si alguien me puede dar alguna pista, se lo agradesco.


saludos!

EI: Juntando mensajes.

nadie sabe en que momento es que estoy escribiendo el byte NULL?


me di cuenta que donde el archivo se corta a la mitad debido a este byte NULL es cuando en el archivo fuente, osea el archivo que estoy duplicando hay un "n", un enter.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: Problema de Byte NULL con archivos
« Respuesta #1 en: Jueves 18 de Septiembre de 2008, 09:25 »
0
¿Te sustituye un 'n' en el fichero origen por un NULL (0x00) en la copia que haces? ¿En el primer 'n' que encuentra?

Rombus

  • Miembro MUY activo
  • ***
  • Mensajes: 105
  • Nacionalidad: ar
    • Ver Perfil
    • http://myspace.com/punkrecycle
Re: Problema de Byte NULL con archivos
« Respuesta #2 en: Jueves 18 de Septiembre de 2008, 14:35 »
0
hola m0skit0!
gracias por responder.

el byte null, se escribe en la copia, el original queda como estaba.
pero igual, es medio raro, porque lo estoy probando con estos archivos:


como original:
Código: Text
  1.    
  2.    
  3.    
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <stdlib.h>
  7. #define aksjdklfj
  8. #include <sempor.h>
  9. void  main(void){
  10.    
  11. }
  12.  
  13.  

(con muchos n's al principio)

y lo que  termina quedando como "salida", osea, mi "duplica" queda asi:
Código: Text
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4.  
  5.  
  6.  

y cuando lo abro al archivo de salida me dice que hay un byte null y que mi archivo fue cortado.

sin embargo, en la consola, me muestra todo como deberia ser :S



osea, el fin de este programa (q en realidad estoy intentando hacer andar la funcion pasaIncludesStd), es agarrar un codigo fuente, y ordenarle todos los #includes <..> al principio, si hay un codigo de la siguiente manera:
Código: Text
  1. #include <stdlib.h>
  2. #define TRUE 1
  3. #include <ctype.h>
  4.  

mi programa deberia organizar los includes para que quede asi:
Código: Text
  1. #include <stdlib.h>
  2. #include <ctype.h>
  3. #define TRUE 1
  4.  


el problema en mi codigo se ve (tomando el archivo de entrada que uso para probarlo) cuando despues
del include <stdlib.h> viene un define, enotnces hay un if bifurcador que si es define no lo pasa al archivo(eso lo va a hacer otra funcion)

pero no puedo corregirlo de ninguna manera :S

saludos!

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: Problema de Byte NULL con archivos
« Respuesta #3 en: Jueves 18 de Septiembre de 2008, 15:10 »
0
Tienes mal la condición aquí:

Código: C
  1.  
  2. #define hastaEOL(a)             while((fgetc(a)!= 'n') && (fgetc(a)  != EOF))
  3.  
  4.  

Así te va a leer siempre hasta el final del fichero, puesto que se tiene que cumplir fgetc(a)  != EOF.

Como habrás adivinado, tiene que ser:

Código: C
  1.  
  2. #define hastaEOL(a)             while((fgetc(a)!= 'n') || (fgetc(a)  != EOF))
  3.  
  4.  

Los errores de lógica como estos son muy comunes, así que cuando escribas condiciones con operadores logicos, haz un par de pruebas mentales o por escrito de la condición. ¡Saludos!

P.D: para los linuxeros, son ficheros. Archivo :no: es nomenclatura de MS, que se inventa los términos.

Rombus

  • Miembro MUY activo
  • ***
  • Mensajes: 105
  • Nacionalidad: ar
    • Ver Perfil
    • http://myspace.com/punkrecycle
Re: Problema de Byte NULL con archivos
« Respuesta #4 en: Jueves 18 de Septiembre de 2008, 15:53 »
0
pero no es al revez?

yo quiero leer hasta el fin de linea.

si hago
Código: Text
  1. while((fgetc(a)!= 'n') || (fgetc(a)  != EOF));
  2.  

y leo el primer enter, ahi terminaria mi linea, pero como no es eof la segunda parte de la condicion seria verdadera, y como es un or la expresion seria evaluada como verdadera.

y si hago:
Código: Text
  1. while((fgetc(a)!= 'n') && (fgetc(a)  != EOF));
  2.  

cuando encuentre el primer enter la primera condicion es falsa y la segunda verdadera pero como es un AND la expresion es falsa, y pasaria lo mismo si encuentro un EOF.


tiene sentido lo q digo?

a estas horas estoy muy quemado de la cabeza jaja



Cita de: "m0skit0"
P.D: para los linuxeros, son ficheros. Archivo :no: es nomenclatura de MS, que se inventa los términos.

ficheros entonces  :good:

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: Problema de Byte NULL con archivos
« Respuesta #5 en: Jueves 18 de Septiembre de 2008, 16:05 »
0
Me encantan estas discusiones  :beer:

Primeramente, tanto una como otra están mal. Se me pasó que de esa manera se leen 2 caracteres diferentes, es decir, la primera fgetc() lee un carácter y la segunda lee el siguiente. Por lo tanto, deberías de hacer un solo fgetc(a) y asignarle el el valor devuelto a un variable y comparar.

Una vez aclarado esto, si utilizamos un AND, como tú dices, sería "lee caracter mientras no sea NI final de línea NI final de fichero", es decir, que leerías TODOS los caracteres del fichero, puesto que la condición se cumple sólo cuando sea tanto EOL como EOF, las 2 A LA VEZ, que sólo se cumple al final del fichero (por EOF).

Sin embargo, si es un OR, pararía de leer tanto si es EOL como si es EOF, es decir, basta que se cumpla una de las dos, no ambas simultáneamente, que es lo que tú quieres. De hecho, la condición de EOF no tiene razón de ser si el fichero termina con "enter".

Espero haberme explicado, que he dormido 4 horas y media   :wacko:  :argh:

Rombus

  • Miembro MUY activo
  • ***
  • Mensajes: 105
  • Nacionalidad: ar
    • Ver Perfil
    • http://myspace.com/punkrecycle
Re: Problema de Byte NULL con archivos
« Respuesta #6 en: Jueves 18 de Septiembre de 2008, 16:30 »
0
me quiero matar

Cita de: "m0skit0"
la primera fgetc() lee un carácter y la segunda lee el siguiente

 :argh:  odio cuando me pasa eso!!

es verdad, ese problema lo tube en otras funciones anteriores y dije: "claro, tengo dos fgetc entonces estoy comparando
con dos valores diferentes"

y en este no me di cuenta.



excelente!

ya esta andando :D

el define se convirtio en funcion:
Código: Text
  1. void hastaEOL(FILE *a){
  2.     char c;
  3.     do{
  4.         c = fgetc(a);
  5.     }while((c != 'n') && (c != EOF));
  6. }
  7.  




con respecto a lo del AND y OR.

no es que cuando yo tengo un OR, y la condicion A es falsa, pero la B es verdadera va a seguir siendo verdadera la expresion, y lo mismo en viceseversa?

en cambio si yo tengo un AND y la condicion A es falsa AND la B es verdadera, entonces es falso, osea, tengo un EOF no un enter, pero es el fin de linea al fin.

osea,

1 AND 0 = 0     //si es enter pero no EOF es falso, fin de linea ;)
1 OR 0 = 1      //si es enter pero no EOF seria verdadero y yo quiero que sea falso, osea, estoy en el fin de linea


gracias m0skit0
un error estupido que no podia ver que me estaba volviendo loco  :D

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: Problema de Byte NULL con archivos
« Respuesta #7 en: Jueves 18 de Septiembre de 2008, 16:53 »
0
Me alegro de que funcione.

Efectivamente, tienes razón  :good: . Mi confusión radica (aparte de haber dormido 5 horas...) en que yo no lo codificaría de esa manera. Me entero mejor así:

Código: C
  1.  
  2. while !(c=='n' || c==EOF)
  3.  
  4.  

Que es exactamente la misma condición que la tuya si aplicamos la Ley de De Morgan.  ^_^