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:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char *nombre;
char *autor;
int cantidad;
int precio;
} Libro;
void liberarMemoria(Libro *libros, int numeroLibros){
for(int i = 0; i < numeroLibros; ++i){
}
}
void guardarLibro(Libro *libros, char *temporal, int numeroLibros){
char *token
= strtok(temporal
, ","); libros
[numeroLibros
-1].
nombre = (char*)malloc((strlen(token
)+1) * sizeof(char)); strcpy(libros
[numeroLibros
-1].
nombre, token
);
libros
[numeroLibros
-1].
autor = (char*)malloc((strlen(token
)+1) * sizeof(char)); strcpy(libros
[numeroLibros
-1].
autor, token
);
libros
[numeroLibros
-1].
cantidad = atoi(token
);
libros
[numeroLibros
-1].
precio = atoi(token
);}
void mostrarLibros(Libro *libros, int numeroLibros){
for(int i = 0; i < numeroLibros; ++i){
printf("***** INFORMACION LIBRO %d *****\n", i
+1); printf("Nombre: %s\n", libros
[i
].
nombre); printf("Autor: %s\n", libros
[i
].
autor); printf("Cantidad: %d\n", libros
[i
].
cantidad); printf("Precio: %d\n", libros
[i
].
precio); }
}
int main(){
Libro *libros = NULL;
char temporal[SIZE];
FILE
*fichero
= fopen("libros.txt", "r");
int numeroLibros = 0;
while(fgets(temporal
, SIZE
, fichero
)) { ++numeroLibros;
libros
= (Libro
*)realloc(libros
, numeroLibros
* sizeof(Libro
)); guardarLibro(libros, temporal, numeroLibros);
}
mostrarLibros(libros, numeroLibros);
liberarMemoria(libros, numeroLibros);
return 0;
}
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.