Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: m@o_614 en 10 Septiembre 2013, 13:12 pm



Título: Lectura y modificacion de archivo
Publicado por: m@o_614 en 10 Septiembre 2013, 13:12 pm
Saludos tengo el siguiente codigo que me lee un archivo de texto y despues lo modifica, en todos los lugares donde se encuentre 1's los intercambia por 5's, la lectura del archivo lo hace bien porque ya verifique y si me ubica los unos del texto el problema es para poder cambiarlos a 5, y no se donde esta el error

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4.  
  5. /*
  6.     Objetivo de la prueba: En una archivo de texto que contiene caracteres alfanuméricos,
  7.     intercambiar el  ‘1’ por el  ‘ 5’ en donde quiera que ocurra esa incidencia en el documento.
  8.     El archivo debe aparecer sin ningún 1, y en su lugar los cincos equivalentes.
  9. */
  10.  
  11. int main()
  12. {
  13.    FILE *fd;
  14.    char letra;
  15.    if((fd = fopen("F:\\archivo_practica11.txt","r+"))!=NULL)
  16.    {
  17.        while(!feof(fd))
  18.        {
  19.            fread(&letra,sizeof(char),1,fd);
  20.            if(letra == '1')
  21.            {
  22.                 letra = '5';
  23.                fwrite(fd,sizeof(char),1,letra);
  24.            }
  25.        }
  26.    }
  27.    else
  28.       printf("No se pudo abrir el archivo");
  29.    return 0;
  30. }
  31.  

gracias


Título: Re: Lectura y modificacion de archivo
Publicado por: eferion en 10 Septiembre 2013, 13:27 pm
Cada vez que lees o escribes estás modificando el puntero interno del fichero.

Quiero decir... cuando tu abres un archivo, internamente se crea un puntero de posición. Este puntero es el que indica a partir de donde se van a iniciar las operaciones de lectura / escritura. Cuando tu realizas una de estas operaciones sobre el fichero, dicho puntero se actualiza. Esta es la razón por la que sucesivas escrituras no machacan la misma información sino que se concatenan.

Tu estás leyendo un carácter y, si éste es un '1', escribes un '5' en el fichero. El problema es que al lanzar la operación de lectura el puntero interno ha avanzado una posición y el '5' machaca la posición siguiente.

Para evitar esto tienes que hacer esto:

Código
  1. fread(&letra,sizeof(char),1,fd);
  2.            if(letra == '1')
  3.            {
  4.                fseek( fd, -1, SEEK_CUR );
  5.                 letra = '5';
  6.                fwrite(fd,sizeof(char),1,letra);
  7.            }

De esta forma vuelves a posicionar el puntero sobre el carácter '1' y la operación de escritura machacará dicho carácter.

No he compilado el código, pero debería funcionar.


Título: Re: Lectura y modificacion de archivo
Publicado por: rir3760 en 10 Septiembre 2013, 17:45 pm
Otro error es utilizar la función feof para controlar el bucle (con ello se realiza una iteración de mas) y uno mas es el orden de los argumentos de la función fwrite:
Código
  1. fwrite(fd, sizeof(char), 1, letra);
El primer argumento debe ser la dirección base (de tipo "void *") y el ultimo el archivo a procesar (de tipo "FILE *").

Y no necesitas del encabezado <unistd.h>. Si no tienes una referencia sobre las funciones de la biblioteca estándar de C (C90) deberías conseguir una, mientras eso sucede una aceptable es Standard C (http://web.archive.org/web/20060901131918/http://www-ccs.ucsd.edu/c/).

Un saludo


Título: Re: Lectura y modificacion de archivo
Publicado por: m@o_614 en 10 Septiembre 2013, 23:30 pm
Gracias por sus respuestas, le habia hecho al codigo unos cambio de los que me habian dicho, pero ahora sucede que aunque el programa si cambia los 1's por los 5's ahora se cicla infinitamente, y creo que el problema esta en el fseek, porque le puse un contador en el ciclo para que me contara cuantos unos aparecian en el texto y si le ponia fseek no me imprimia nada y si se lo quitaba ya me imprimia correctamente

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4.  
  5. /*
  6.     Objetivo de la prueba: En una archivo de texto que contiene caracteres alfanuméricos,
  7.     intercambiar el  ‘1’ por el  ‘ 5’ en donde quiera que ocurra esa incidencia en el documento.
  8.     El archivo debe aparecer sin ningún 1, y en su lugar los cincos equivalentes.
  9. */
  10.  
  11. int main()
  12. {
  13.   FILE *fd;
  14.   char letra;
  15.   int i = 0;
  16.   if((fd = fopen("F:\\archivo2.txt","r+"))!=NULL)
  17.   {
  18.       while(!feof(fd))
  19.       {
  20.           fread(&letra,sizeof(char),1,fd);
  21.           if(letra == '1')
  22.           {
  23.               fseek(fd,-1,SEEK_CUR);
  24.               letra = '5';
  25.               fwrite(&letra,sizeof(char),1,fd);
  26.               i++;
  27.           }
  28.       }
  29.       printf("%d",i);
  30.   }
  31.   else
  32.      printf("No se pudo abrir el archivo");
  33.   return 0;
  34. }
  35.  


Título: Re: Lectura y modificacion de archivo
Publicado por: eferion en 10 Septiembre 2013, 23:48 pm
Ese printf está fuera de los ciclos... salta cuando haya terminado de procesar el archivo...

Código
  1. if((fd = fopen("F:\\archivo2.txt","r+"))!=NULL)
  2.   {
  3.       while(!feof(fd))
  4.       {
  5.           // ...
  6.       }
  7.       printf("%d",i);
  8.   }

y si has abierto el archivo, no te olvides de cerrarlo al final con fclose.


Título: Re: Lectura y modificacion de archivo
Publicado por: m@o_614 en 11 Septiembre 2013, 03:16 am
En realidad ese printf y el contador ps no sirven para nada, solo queria saber si me estaba contando bien cuantos unos habia, pero ahora ya me di cuenta que el fseek no es el problema!! el problema es cuando le asigno a letra un nuevo valor o en el fwrite, no se bien

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4.  
  5. /*
  6.     Objetivo de la prueba: En una archivo de texto que contiene caracteres alfanuméricos,
  7.     intercambiar el  ‘1’ por el  ‘ 5’ en donde quiera que ocurra esa incidencia en el documento.
  8.     El archivo debe aparecer sin ningún 1, y en su lugar los cincos equivalentes.
  9. */
  10.  
  11. int main()
  12. {
  13.   FILE *fd;
  14.   char letra;
  15.   int n;
  16.   if((fd = fopen("F:\\archivo2.txt","r+"))!=NULL)
  17.   {
  18.          fread(&letra,sizeof(char),1,fd);
  19.           if(letra == '1')
  20.           {
  21.               fseek(fd,-1,SEEK_CUR);
  22.               letra = '5';
  23.               printf("%c",fgetc(fd));
  24.   }
  25.   else
  26.      printf("No se pudo abrir el archivo");
  27.   return 0;
  28. }
  29.  

en el printf que tiene el fgetc  queria ver si la variable letra habia cambiado a 5 pero ya vi que me sigue imprimiendo los unos, me imagino que por ahi esta el problema


Título: Re: Lectura y modificacion de archivo
Publicado por: eferion en 11 Septiembre 2013, 08:17 am
Código
  1. fread(&letra,sizeof(char),1,fd);
  2.           if(letra == '1')
  3.           {
  4.               fseek(fd,-1,SEEK_CUR);
  5.               letra = '5';
  6.               printf("%c",fgetc(fd));
  7.            }

A ver tu estás haciendo "letra = 5", es decir, estas asignando a una variable de tu programa el valor 5 y, acto seguido, lees del archivo con fgetc... obviamente la asignación no va a afectar al archivo si no le metes un fwrite.

Si quieres hacer esta comprobación tendrás que hacer algo así:

Código
  1. fread(&letra,sizeof(char),1,fd);
  2.           if(letra == '1')
  3.           {
  4.               fseek(fd,-1,SEEK_CUR);
  5.               letra = '5';
  6.               fwrite( &letra, sizeof(char), 1, fd ); // primero modificamos el fichero
  7.               fseek( fd, -1, SEEK_CUR ); // retrocedemos otra vez para poder leer
  8.               printf("%c",fgetc(fd)); // y ahora si leemos lo que deberia ser un 5
  9.            }


Título: Re: Lectura y modificacion de archivo
Publicado por: rir3760 en 11 Septiembre 2013, 19:20 pm
le habia hecho al codigo unos cambio de los que me habian dicho, pero ahora sucede que aunque el programa si cambia los 1's por los 5's ahora se cicla infinitamente
El problema se debe a que en los modos de actualización ("r+", "w+" y "a+") las operaciones de lectura y escritura no pueden realizarse una inmediatamente después de la otra. Siempre después de una operación de lectura se debe indicar la posición en el archivo mediante fseek o rewind si la intención es continuar con una operación de escritura (y al revés): lectura <==> posicionamiento <==> escritura.

En tu caso eso no sucede porque si el carácter '1' se encuentra en el archivo lo sobrescribes con un '5' y a continuación (en la siguiente iteración del bucle) tratas de leer el siguiente carácter, ahí falta la mentada llamada a función.

Para que el programa funcione correctamente se puede utilizar la función ftell para obtener las posiciones antes y después de la lectura del carácter:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(void)
  5. {
  6.   FILE *stream;
  7.   long a;
  8.   long b;
  9.   char ch;
  10.  
  11.   if ((stream = fopen("Entrada.txt", "r+")) != NULL){
  12.      while (a = ftell(stream), fread(&ch, 1, 1, stream) == 1){
  13.         if (ch == '1'){
  14.            b = ftell(stream);
  15.  
  16.            fseek(stream, a, SEEK_SET);
  17.            ch = '5';
  18.            fwrite(&ch, 1, 1, stream);
  19.            fseek(stream, b, SEEK_SET);
  20.         }
  21.      }
  22.  
  23.      fclose(stream);
  24.   }
  25.  
  26.   return 0;
  27. }

Un saludo


Título: Re: Lectura y modificacion de archivo
Publicado por: m@o_614 en 12 Septiembre 2013, 01:58 am
muchas gracias rir3760 nunca se me hubiera ocurrido que cuando haces una actualizacion no se puede leer y despues escribir luego. Una ultima pregunta, por que antes del fread siempre se tiene que utilizar el ftell???


Título: Re: Lectura y modificacion de archivo
Publicado por: rir3760 en 12 Septiembre 2013, 15:40 pm
por que antes del fread siempre se tiene que utilizar el ftell?
Porque no sabemos de antemano si el carácter que vamos a leer cumplirá o no con la condición, si es igual a '1' debemos regresar a la posición anterior (ftell + fseek) y sobrescribir ese carácter (fwrite).

Un saludo