/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Cambiar la longitud de los strings de un archivo

 
      Índice del Foro elrincondelc.com -> C/C++ en General
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
radicaled



Registrado: 07 Nov 2006
Mensajes: 26

MensajePublicado: 02/11/2007 4:40 pm
Título: Cambiar la longitud de los strings de un archivo

Gente, estoy con un problemilla. Tengo un archivo de texto, en cada linea la longitud del string varia. El problema es que no lo puedo leer secuencialmente como dios manda (por que es uno de los objetivos del ejercicio), si no que lo tengo que leer a partir de indices.
Ahora, como tengo indices tengo que usar el fseek, pero al variar la longitud de la cadena de caracteres en cada linea no lo puedo usar.
Hice un pequeño programa para que me varie la longitud del archivo, pero no se que estoy haciendo mal que no lo hace.
Les paso el codigo a ver si alguien se da cuenta, gracias

Código:
 
      char dicc[] = "diccionario.txt";
          char dicc2[] = "diccionario";
          char palabra[50];
          char aux[50];

          FILE *dic;
          FILE *dicaux;

          memset(palabra, '\0', 50);

          if ((dic = fopen(dicc,"r+")) == NULL){
              printf("Hubo un error en la apertura del archivo diccionario\n");
              fclose(dic);
          }

          if ((dicaux = fopen(dicc2,"w+")) == NULL){
              printf("Hubo un error en la apertura del archivo diccionario\n");
              fclose(dicaux);
          }

          if (!fscanf(dic, "%s",palabra)){
              printf("No se puede leer la linea del archivo\n");
              fclose(dic);
          }

          strncpy (aux, palabra, 50);
          fprintf(dicaux, "%s\n",aux);

          while (!feof(dic)){
              memset(palabra, '\0', 50);
              if (!fscanf(dic, "%s",palabra)){
                  printf("No se puede leer la linea del archivo\n");
                  fclose(dic);
              }
              strncpy (aux, palabra, 50);
              fprintf(dicaux, "%s\n",aux);

          }

          fclose(dic);
          fclose(dicaux);
          remove ("diccionario.txt");
          rename ("diccionario", "diccionario.txt");
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3896
Ubicación: Mexico

MensajePublicado: 02/11/2007 8:45 pm
Título:

Si tienes un archivo de texto plano con cada linea separada de la siguiente por avances de linea no puedes utilizar las funciones fseek y ftell de la misma forma que en archivos binarios, los detalles tecnicos en este momento no los recuerdo pero puedo asegurarte que ese no es el camino.

En lo que respecta a tu programa este tiene bastantes errores de concepto:

* Cuando abres un archivo si la funcion fopen falla imprimes un mensaje de error con printf cuando seria mejor utilizar perror y dejar que sea el entorno el que genere el mensaje de error apropiado, tampoco es posible cerrar el archivo ya que si fopen falla el archivo para empezar no esta abierto.

* En las verificaciones de errores que siguen a las aperturas de los archivos si ocurre un error cierras el archivo pero no terminas el programa.

* Las operaciones de este bloque:
Código:
strncpy (aux, palabra, 50);
fprintf(dicaux, "%s\n",aux);

Son complicadas de forma innecesaria: si al final vas a escribir la cadena almacenada en "palabra" en el stream "dicaux" deberias hacerlo directamente.

* En el bucle que controla la lectura de datos utilizas feof para controlar la salida de este y el uso de esta funcion no es recomendable en un caso asi porque (¿Cuantas van? ¿Candidato seguro a las FAQ?) esa funcion SOLO devuelve un valor verdadero DESPUES que una funcion trata de leer datos del stream y falla debido a que ya no hay mas datos que leer.

Ese bloque:
Código:
if (!fscanf(dic, "%s",palabra)){
   printf("No se puede leer la linea del archivo\n");
   fclose(dic);
}

strncpy (aux, palabra, 50);
fprintf(dicaux, "%s\n",aux);

while (!feof(dic)){
   memset(palabra, '\0', 50);
   
   if (!fscanf(dic, "%s",palabra)){
      printf("No se puede leer la linea del archivo\n");
      fclose(dic);
   }
   
   strncpy (aux, palabra, 50);
   fprintf(dicaux, "%s\n",aux);
}


Se puede reducir a:
Código:
while (fscanf(dic, "%s", palabra) == 1)
   fprintf(dicaux, "%s\n", palabra);
if (ferror(dic)){

   /* manejo de error */
   
}


Por ultimo tienes que considerar que al utilizar scanf con el indicador de tipo "%s" no estas procesando lineas de texto sino palabras.

Si por alguna razon debes manejar lineas de texto en base a indices necesitarias de dos archivos (ambos en formato binario): el primero contendria las lineas de texto una despues de la otra sin ningun tipo de delimitador mientras que el segundo (los indices) incluiria la posicion de inicio de cada cadena.

Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
radicaled



Registrado: 07 Nov 2006
Mensajes: 26

MensajePublicado: 03/11/2007 1:15 am
Título:

perfecto muchas gracias.
Ahora el no poder usar el fseek para buscar una linea especifica, que deberia hacer, cuando genero el archivo nuevo en vez de que sea de texto que sea binario?? o hay una funcion parecida para los archivos de texto.

GRacias
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3896
Ubicación: Mexico

MensajePublicado: 03/11/2007 9:50 am
Título:

radicaled escribió:
Ahora el no poder usar el fseek para buscar una linea especifica, que deberia hacer, cuando genero el archivo nuevo en vez de que sea de texto que sea binario??

Exacto.

radicaled escribió:
o hay una funcion parecida para los archivos de texto.

No la hay, vas a tener que desarrollar una funcion propia.

----

Para explicar el proceso en mas detalle: los dos archivos son binarios.

* El archivo de datos contiene los caracteres que forman cada linea pero sin ningun tipo de delimitador ('\n', '\r' o cualquier otra secuencia propia del entorno).

* El archivo de indices contiene, en la forma de enteros sin signo, la posicion de inicio de cada linea de texto en el archivo de datos.

Por ejemplo si al inicio de tu programa tienes dos lineas de texto:
Código:
1) "Hola, mundo"       ==> 11 caracteres
2) "Adios mundo cruel" ==> 17 caracteres


Abres ambos archivos binarios ("datos" e "indices"), en el primero imprimes ambas cadenas como tu quieras (fputc, fread, etc.) de nuevo sin ningun tipo de delimitador. Esta carencia la suples al almacenar (en formato binario) en el archivos de indices los dos valores 0 y 11, el primero indica la posicion de inicio de la primera cadena "Hola, mundo" y el segundo la posicion de inicio de la segunda cadena "Adios mundo cruel".

De esta forma si requieres informacion sobre la linea N solo tienes que leer el entero N del archivo de indices y si requieres de la longitud de esta basta con restar el entero N + 1 del entero N para obtener su longitud. Esta solucion esta bien lejos de ser perfecta porque tendrias que tratar a la ultima cadena como un caso especial y solo te permite lectura y adicion de cadenas.

Si quieres insercion y eliminacion hasta donde tengo entendido no hay solucion facil y eficiente.

Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
radicaled



Registrado: 07 Nov 2006
Mensajes: 26

MensajePublicado: 03/11/2007 10:37 am
Título:

Muchas gracias denuevo Wink
Volver arriba
      Índice del Foro elrincondelc.com -> C/C++ en General
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com