elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: AIO elhacker.NET 2021 Compilación herramientas análisis y desinfección malware


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  estructuras y lectura de archivos en C
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: estructuras y lectura de archivos en C  (Leído 2,293 veces)
michellcrh

Desconectado Desconectado

Mensajes: 14


Ver Perfil
estructuras y lectura de archivos en C
« en: 30 Mayo 2020, 06:25 am »

 :-\Hola tengo que realizar un programa haciendo uso de estructuras dinamicas y lectura de archivos, pero no puedo hacer correctamente la extracción de los archivos y guardarlos en arreglos.
Solo guarda el nombre y la cantidad, pero el autor y el precio no.

Este es mi código:
Código
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4.  
  5. typedef struct{
  6.    char *nombre;
  7.    char *autor;
  8.    int cantidad;
  9.    int precio;
  10. }libros;
  11. libros *l;
  12.  
  13. void menu();
  14. void vaciar(char temp[]);
  15. void copiarNombre(char temp[],int i);
  16. void copiarAutor(char temp[],int i);
  17.  
  18. int main(){
  19.    char temp[50],aux;
  20.    int contador = 0;
  21.  
  22.    FILE *fichero;
  23.    fichero = fopen("libros.txt","rt");
  24.    if(fichero == NULL){
  25.        printf("No se ha encontrado el documento\n");
  26.        return 0;
  27.    }
  28.    while(!feof(fichero)){
  29.        fgets(temp,50,fichero);
  30.        contador++;
  31.    }
  32.    rewind(fichero);
  33.    l = (libros*)malloc(contador*sizeof(libros));
  34.    if(l == NULL){
  35.        printf("NO SE HA PODIDO RESERVAR LA MEMORIA\n");
  36.        return 0;
  37.    }
  38.    for(int i=0;!feof(fichero); i++){
  39.        vaciar(temp);
  40.        aux = '0';
  41.        for(int j=0; aux != ','; j++ ){
  42.                aux = fgetc(fichero);
  43.                if(aux != ','){
  44.                    temp[j] = aux;
  45.                }
  46.        }
  47.        copiarNombre(temp,i);
  48.        copiarAutor(temp,i);
  49.        fgets(temp,4,fichero);
  50.        l[i].cantidad = atoi(temp);
  51.        fgets(temp,5,fichero);
  52.        l[i].precio = atoi(temp);
  53.       printf("Precio: %d\n",l[i].precio);
  54.  
  55.    }
  56.    fclose(fichero);
  57.  
  58.    getchar();
  59.    return 0;
  60. }
  61.  
  62. void menu(){
  63.    int opc;
  64.  
  65.    printf("\t\t\tLIBRERIA FI\n\n");
  66.    printf("1. Leer inventario inicial\n");
  67.    printf("2. Mostrar inventario de existencias\n");
  68.    printf("3. Vender libros\n");
  69.    printf("4. Informe de ventas\n");
  70.    printf("5. Salir\n");
  71.    printf(" \nIngrese el numero correspondiente a la operacion que desea realizar: ");
  72.    scanf("%d",&opc);
  73. }
  74.  
  75. void vaciar(char temp[]){
  76.    for(int i=0; i<50; i++){
  77.        temp[i] = '\0';
  78.    }
  79. }
  80.  
  81. void copiarNombre(char temp[],int i){
  82.    int longitud;
  83.    longitud = strlen(temp)+1;
  84.    l[i].nombre = (char*)malloc(longitud*sizeof(char));
  85.    if(l[i].nombre == NULL){
  86.        printf("No se ha podido reservar memoria\n");
  87.        return 0;
  88.    }
  89.    strcpy(l[i].nombre,temp);
  90. }
  91.  
  92. void copiarAutor(char temp[],int i){
  93.    int longitud;
  94.    longitud = strlen(temp)+1;
  95.    l[i].autor = (char*)malloc(longitud*sizeof(char));
  96.    if(l[i].autor == NULL){
  97.        printf("No se ha podido reservar memoria\n");
  98.        return 0;
  99.    }
  100.    strcpy(l[i].autor,temp);
  101. }


mi archivo de texto es el siguiente:
Código:
La casa de los espiritus,Isabel Allende,5,345
La Metamorfosis,Franz Kafka,3,560
La Odisea,Homero,7,200
El Principito,Antoine de Saint-Exupery,2,499
El Laberinto de la Soledad,Octavio Paz,1,150
El tunel,Ernesto Sabato,3,100
Los miserables,Victor Hugo,5,290
Cuentos de amor de locura y de muerte,Horacio Quiroga,4,563
El amor en lo tiempos de colera,Gabriel Garcia Marquez,6,218


MOD: Utiliza las etiquetas de Código GeSHi para los fragmentos de código


« Última modificación: 30 Mayo 2020, 08:26 am por YreX-DwX » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: estructuras y lectura de archivos en C
« Respuesta #1 en: 30 Mayo 2020, 11:30 am »

El problema principal es la separación que estás haciendo en tokens o partes.
Buscas hasta la primera coma (,) para localizar el nombre del libro pero de seguido guardas el nombre del autor también sin haber buscado hasta la siguiente coma. Por lo tanto, el nombre del libro y el autor siempre son la misma cadena.
A partir de ahí ya se descuadran todos los cálculos (que tampoco entiendo esos fgets() con longitud 4 y 5...) y se guarda todo mal.

Además otro problema es que la cadena que usas para guardar cada línea del fichero temporalmente tiene una longitud de 50 y hay líneas que superan ese número de caracteres por lo que los caracteres que no entran en una línea, se leen en la siguiente.

Otro otro tema importante cuando se trabaja con memoria dinámica es que esa memoria tienes que liberarla manualmente usando free().

Y otro tema es usar return para salir en caso de error. En la función main() se puede hacer porque de un return acaba el programa pero en otras funciones auxiliares, llamar a return lo que hace es devolver el control a la función que llamó a esta. Es más correcto utilizar exit().
Además el valor 0 se suele asociar a que todo ha finalizado correctamente. Para errores es mejor usar -1. En conjunto: exit(-1).

Otros consejos son:
  • Utilizar una constante para la longitud de la cadena que te permita modificarlo rápidamente sin tener que ir mirando por todo el código.
  • No utilizar variables globales, como en tu caso el puntero l.
  • Para separar una cadena en base a un patrón o varios tienes la función strtok().
  • Para "vaciar" una cadena no es necesario poner '\0' a todas sus posiciones. Basta con hacerlo en la posición 0.

Te dejo otra forma de hacerlo con las modificaciones antes mencionadas:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define SIZE 100
  6.  
  7. typedef struct {
  8. char *nombre;
  9. char *autor;
  10. int cantidad;
  11. int precio;
  12. } Libro;
  13.  
  14.  
  15. void liberarMemoria(Libro *libros, int numeroLibros){
  16. for(int i = 0; i < numeroLibros; ++i){
  17. free(libros[i].nombre);
  18. free(libros[i].autor);
  19. }
  20. free(libros);
  21. }
  22.  
  23. void guardarLibro(Libro *libros, char *temporal, int numeroLibros){
  24. char *token = strtok(temporal, ",");
  25. libros[numeroLibros-1].nombre = (char*)malloc((strlen(token)+1) * sizeof(char));
  26. strcpy(libros[numeroLibros-1].nombre, token);
  27.  
  28. token = strtok(NULL, ",");
  29. libros[numeroLibros-1].autor = (char*)malloc((strlen(token)+1) * sizeof(char));
  30. strcpy(libros[numeroLibros-1].autor, token);
  31.  
  32. token = strtok(NULL, ",");
  33. libros[numeroLibros-1].cantidad = atoi(token);
  34.  
  35. token = strtok(NULL, ",");
  36. libros[numeroLibros-1].precio = atoi(token);
  37. }
  38.  
  39. void mostrarLibros(Libro *libros, int numeroLibros){
  40. for(int i = 0; i < numeroLibros; ++i){
  41. printf("***** INFORMACION LIBRO %d *****\n", i+1);
  42. printf("Nombre: %s\n", libros[i].nombre);
  43. printf("Autor: %s\n", libros[i].autor);
  44. printf("Cantidad: %d\n", libros[i].cantidad);
  45. printf("Precio: %d\n", libros[i].precio);
  46. printf("\n");
  47. }
  48. }
  49.  
  50. int main(){
  51. Libro *libros = NULL;
  52. char temporal[SIZE];
  53. FILE *fichero = fopen("libros.txt", "r");
  54.  
  55. int numeroLibros = 0;
  56. while(fgets(temporal, SIZE, fichero)) {
  57. ++numeroLibros;
  58. libros = (Libro*)realloc(libros, numeroLibros * sizeof(Libro));
  59. guardarLibro(libros, temporal, numeroLibros);
  60. }
  61.  
  62. mostrarLibros(libros, numeroLibros);
  63.  
  64. liberarMemoria(libros, numeroLibros);
  65. return 0;
  66. }

PD: Cuando vayas a insertar código utiliza etiquetas de Código GeSHi y selecciona el lenguaje que corresponda a tu código. En tu mensaje anterior ya te las he incluido yo pero para otra ocasión.

PD 2: Aunque no es relevante, el menú que tienes no funciona. Si vas a pedir una opción tendrás que devolverla con un return.


En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
michellcrh

Desconectado Desconectado

Mensajes: 14


Ver Perfil
Re: estructuras y lectura de archivos en C
« Respuesta #2 en: 2 Junio 2020, 00:08 am »

Te lo agradezco mucho :)
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
foto lectura, y lectura veloz, scanning y otros metodos de lectura rapida....
Foro Libre
Kase 3 12,665 Último mensaje 4 Febrero 2014, 08:47 am
por camilo_
lectura de archivos
Software
mapers 2 1,983 Último mensaje 19 Enero 2011, 11:56 am
por palomitero
Estructuras y archivos en c++
Programación C/C++
Luifs 5 2,950 Último mensaje 8 Junio 2013, 02:27 am
por rir3760
Lectura de archivos log
Programación C/C++
mauricioPaz19922 2 1,837 Último mensaje 15 Noviembre 2014, 17:35 pm
por Miky Gonzalez
Lectura de archivos C++
Programación C/C++
Azdepredador 3 1,919 Último mensaje 28 Enero 2016, 16:35 pm
por Carlos D. Alvarez
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines