Ir al contenido



Foto

Almacenar información por linea en lenguaje C

[#C]

  • Por favor identifícate para responder
6 respuestas en este tema

#1 Laura C

Laura C

    Newbie

  • Miembros
  • Pip
  • 4 mensajes

Escrito 22 febrero 2018 - 03:50

Buenos días, 
 
Estoy empezando a programar y por lo tanto son pocas las funciones que conozco. Debo hacer un programa que lea un archivo txt y almacene la información de cada linea de tal manera que pueda utilizarla después para hacer operaciones. 
 
El problema es que hasta el momento solo se como mostrar la información del archivo y no se como llamar cada linea. Agradecería cualquier ayuda o tip que pudieran darme. 
 
Este es el código que tengo hasta ahora


php
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. int i;
  6. char nombre[10]="datos.dat", linea[81];
  7. FILE *fichero;
  8. fichero = fopen( "C:\\Prueba\\guia(1).txt","r");
  9. printf( "Fichero: %s -> ", nombre );
  10. if( fichero )
  11. printf( "existe (ABIERTO)\n" );
  12.  
  13. else
  14. {
  15. printf( "Error (NO ABIERTO)\n" );
  16. return 1;
  17. }
  18.  
  19. printf( "La primera linea del fichero: %s\n\n", nombre );
  20. printf( "%s\n", fgets(linea, 81, fichero) );
  21.  
  22. printf( "DATOS DE LOS PEDIDOS \n\n");
  23. for (i = 0; i< 20; i++)
  24. {
  25. printf( "%s\n", fgets(linea, 81, fichero) );
  26. }
  27.  
  28. if( !fclose(fichero) )
  29. printf( "\nFichero cerrado\n" );
  30. else
  31. {
  32. printf( "\nError: fichero NO CERRADO\n" );
  33. return 1;
  34. }
  35.  
  36. return 0;
  37. }


  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.198 mensajes
  • LocationArgentina

Escrito 22 febrero 2018 - 07:50

Buenas noches Laura C, ¡Bienvenida a DelphiAcess! Esperamos que esta comunidad se convierta en tu segundo hogar y te sientas cómda.

 

No soy el más indicado para asesorarte en tu duda ya que desconozco C, pero ya que uso algo de PHP y el lenguaje grand-mater de éste tiene sus orígenes en C es bastante probable que sea algo similar en algunos aspectos.

 

Por lo que estoy leyendo de esta página, para escribir en el archivo se debe de usar fputs() o bien fprintf(). Tu estás invocando a una printf().

Para leerlo se usa fgets(), y esta función por si misma va desplazandose. Es decir, si le indicas que lea 8 caracteres, después de invocarla ahora el cursor del archivo apuntará al 9vo. Si ahora lees 4, fgets() hará que el cursor del archivo apunte al 13vo.

Para leer el archivo completo necesitas un ciclo para iterar desde el comienzo hasta el final. Ahora bien, Hay dos alternativas:

1. Que antes de abrirlo, o bien, inmediatamente al abrirlo, leas el tamaño del archivo y vayas contando los bytes para saber si llegaste al final.

2. Hacer un ciclo que itere mientras no se haya llegado a fin de archivo leyendo la función eof().

 

EDITO:

Ahora bien, si quieres posicionarte en una "linea" en particular, la enorme mayoría de los lenguajes llaman a esta función seek, que para el caso de C y viendo el estilo de nomeclatura lo de esperarse es que ésta se llame fseek(). Es más es una de las formas (o quizá la única) de saber el tamaño del archivo es justamente hacer un seek() desde el final para hacer que el cursor este alli. El tamaño del archivo será el valor que regresa seek, más el tamaño en bytes del contenido del buffer que se pretende leer. Es decir, que si seek() nos devuelve 56, quiere decir que estamos en el byte 56-esimo y nuestro tamaño del buffer es 4 bytes el archivo es de 60 bytes.

 

Creo que el link que puse es lo suficiente ilustrativo.

De todas formas ya llegarán otros compañeros que estén más filosos y familiarizados con C y sepan guiarte.

 

Espero al menos haberte dado algún norte.

 

Saludos,


  • 1

#3 Laura C

Laura C

    Newbie

  • Miembros
  • Pip
  • 4 mensajes

Escrito 27 febrero 2018 - 09:52

Gracias Delphius! 

 

Estoy revisando tanto el link como la función que me dices para ver que puedo ir haciendo. Había estado intentando crear un array que almacenara la información de  cada linea pero no me ha funcionado o tal vez no sea posible hacer eso. De igual manera esperaré que otra respuestas puedan darme. 

 

Muchas gracias por la información y tu bienvenida. 


  • 0

#4 Laura C

Laura C

    Newbie

  • Miembros
  • Pip
  • 4 mensajes

Escrito 01 marzo 2018 - 08:11

Buenos días, he estado tratando de lograr algo con este archivo y creo que el problema radica en que las filas no tienen igual longitud: 

 

5 3 1.3
3 2 1 2 3 3 1 2 4 2 1 1 3 5
3 3 1 1 2 2 3 3 1 2 2 2 1 4 3 1
 
Por lo tanto creo que lo mas efectivo es agregar ceros para generar una matriz e incluir todo en un Array de dos dimensiones, cosa que ya probé y funciona bastante bien. El problema es que tuve que ingresar los ceros de forma manual y al aplicar el programa en otro txt con mas información se vuelve bastante engorroso. 
 
Si pudieran brindarme alguna guía de cómo hallar la linea con mayor cantidad de datos y luego agregar el número de ceros restantes a las demás filas les agradecería demasiado. 
 
 
PD/ El fseek no me resultó muy útil para el objetivo general del programa puesto que solo logra posicionarme en determinada parte del archivo, pero lo aplicaré de otra forma más adelante. Ningún conocimiento está de más y menos cuando se está iniciando :3. 

  • 0

#5 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.801 mensajes
  • LocationMadrid - España

Escrito 01 marzo 2018 - 01:26

Bienvenida Laura C

C tiene varios sistemas de manejar archivos. Para el cometido de este tema la elección de las funciones tipo stream (flujos) es corecta centrando en el uso de fopen(),  fgets(), fputs() y fclose (). Existe otro modo llamado de bajo nivel que es menos apropiado para el tema propuesto en el hilo.

Para leer o escribir deberemos tener un buffer del tamaño suficiente para amarcar una línea completa. En este punto hay que decir que no tienen porqué tener la misma longitud.

La elección de una matriz de dos dimensiones es correcta pero ello no implica que todas las lineas deban ser del mismo tamaño como sugiere Laura C. Me explico. Un array es un puntero a un bloque de elementos, en concreto apunta al primar elemento. Un array de dos dimensiones no es otra cosa que un array de punteros. Una cadena de texto en C es un array de caracteres terminando en nulo.
El nombre de la cadena, como buen array, es un puntero al elemento 0.

 

En definitiva:
char **Cadenas es un array de cadenas pero tenemos que reservar espacio dinámicamente.
char *Cadenas[] sería lo mismo.
char *Cadenas[10] Reserva de forma estática 10 punteros char* para 10 Cadenas. Cada cadena de la longitud que queramos y no está reservado ese espacio.

Ahora la pregunta es ¿necesitamos que sea una matriz estática o dinámica? ¿Podemos usar sintaxis C++ (operadores new y delete) o no?
Es aconsejable usar un puntero nulo cómo última cadena para hallar el fin cómo se hace con las cadenas estilo C.

Una vez armado el array y relleno con los datos leídos del archivo, se opera y se guarda línea a línea (cadena a cadena) con fputs sin olvidar poner un '\n' (new line) al final de cada línea guardada.

Saludos.


  • 1

#6 Laura C

Laura C

    Newbie

  • Miembros
  • Pip
  • 4 mensajes

Escrito 01 marzo 2018 - 09:24

¡Muchas gracias Escafandra!

 

La condición que me dieron fue utilizar únicamente lenguaje C. En este caso la matriz sería dinámica porque no siempre tendré el mismo número de filas (la idea es utilizarlo con otros txt que tengo almacenados), entonces supongo que el char también sería dinámico (aunque corrígeme si no es así n_nU).

 

Me da algo de pena preguntar porque tal vez sea algo muy básico u///u , pero ¿de esta manera podría pedir al programa que retorne el dato localizado en una posición específica? 

 

es decir, si en el archivo txt tengo estas tres cadenas: 

 

5 3 1.3
3 2 1 2 3 3 1 2 4 2 1 1 3 5
3 3 1 1 2 2 3 3 1 2 2 2 1 4 3 1
 
y quiero saber que número hay en el espacio 3 de la segunda cadena (3 2 1 2 3 3 1 2 4 2 1 1 3 5), ¿es posible hacer eso utilizado un char?

  • 0

#7 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.801 mensajes
  • LocationMadrid - España

Escrito 02 marzo 2018 - 03:06

Tienes dos opciones, dependiendo de lo que precises globalmente.

1º Leer todas las lineas para ir a la que te interesa y leer el tercer carácter Linea[2] (recuerda que se empieza en 0)

2º Colocar el puntero de archivo en ese lugar (fseek) y luego lo lees directamente con fgetc. Para esto debes conocer con toda exactitud le poción en el archivo.

 

Debes saber si está escrito en modo texto o binario, La diferencia está en como se guarda el retorno de línea: "\r\n" ó "\n". Esto implica un carácter de más o de menos por línea y determinará la posición del carácter buscado si usas fseek(). Veo también que pones espacios en blanco entre caracteres y que en algún sitio hay un "punto" no se si es así como esta en el archivo. "Todos los caracteres cuentan"

 

Suponiendo que el archivo es exactamente como describes, esto es un ejemplo muy simple se leer el sato que pides:


cpp
  1. char Buffer[256];
  2. *Buffer = 0;
  3.  
  4. // Abrimos fichero en modo binario
  5. FILE* hFile = fopen("File.txt", "rb");
  6. if(!hFile) return;
  7.  
  8. // Lectura de dos líneas
  9. fgets(Buffer, sizeof(Buffer), hFile);
  10. fgets(Buffer, sizeof(Buffer), hFile);
  11.  
  12. Buffer[4]; // El carácter que buscas contando los espacios...
  13.  
  14. fclose(hFile);
  15. return;

Ahora te pongo un ejemplo más complejo usando un array estático de cadenas dinámicas como expuse aquí.


cpp
  1. {
  2. int n;
  3. FILE* hFile;
  4. char *Lineas[256];
  5. char Buffer[256];
  6. char *C;
  7.  
  8. // Inicializamos, aunque esto no es muy necesario, es buena costumbre
  9. *Buffer = 0;
  10. *Lineas = 0;
  11.  
  12. // Abrimos fichero para leer en modo binario
  13. hFile = fopen("File.txt", "rb");
  14. if(!hFile) return;
  15.  
  16. // Bucle de lectura
  17. for(n = 0; fgets(Buffer, sizeof(Buffer), hFile); n++){
  18. // Eliminamos el retorno de carro y línea "\r\n"
  19. for(C = Buffer; *C && *C != '\r' && *C != '\n'; C++); *C = 0;
  20. // Reservamos memoria
  21. char *Cadena = (char*)malloc(strlen(Buffer));
  22. // Copiamos el buffer en la cadena reservada y la asignamos al array de cadenas
  23. Lineas[n] = strcpy(Cadena, Buffer);
  24. }
  25. Lineas[n] = 0; // Marcamos el fin de líneas
  26.  
  27.  
  28. // Aquí el código para manejar las líneas leídas....
  29. // Las lineas están en el array Lineas al que accedemos con in índice empezando en 0
  30. // Cuando la línea sea un puntero null indica que se acabaron
  31.  
  32.  
  33. // Cerrando el archivo
  34. fclose(hFile);
  35.  
  36. // Liberando memoria
  37. for(n =0; Lineas[n]; n++) free(Lineas[n]);
  38.  
  39. return;
  40. }

Esta es una forma de hacerlo pero no la única. Espero que los comentarios sean claros.

 

 

Saludos.


  • 0