| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
radicaled
Registrado: 07 Nov 2006 Mensajes: 26
| Publicado: 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
| Publicado: 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
| Publicado: 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
| Publicado: 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
| Publicado: 03/11/2007 10:37 am | | | Título: |
| Muchas gracias denuevo  |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |