I am doing a small project for college (1st semester doing a bookstore implementation) and I have a problem with reading from a text file into a list of structs, with a two-dimensional array of characters in it that stores authors. However, it doesn't work properly (every time I launch the program it shows list is empty). Writing to a file works (I think, because it overwrites my text file with empty data).
Example data:
Adam Mickiewicz///Pan Tadeusz/Publisher 1/1833/24.99 Jules Verne///Around The World in 80 days/Publisher 1/1904/19.99 Jean-Jacques Sempe/Rene Goscinny//Little Nicholas/Publisher 2/1963/22.99 My structure:
#define AK 3 // Constant denoting max number of authors typedef struct { char authors[AK][100]; char title[255]; char publisher[100]; unsigned int year; double price; struct Book *next; } Book; Book *first; // Address of the first element in a list Reading from file:
void read_from_file(const char *path) { int no_of_authors; int i; printf("Loading...\n"); FILE *fp = fopen(path, "r"); // Opening a file // Checking for errors if (!fp) { printf("Error reading from file!"); return; } // The loading mechanism no_of_authors = 0; while (!feof(fp)) { Book *new = (Book*) malloc(sizeof(Book)); for (i = 0; i < AK; i++) { fscanf(fp, "%s/", new->authors[i]); } fscanf(fp, "%s/%s/%u/%lf", new->title, new->publisher, &new->year, &new->price); fscanf(fp, "\n"); new = new->next; } fclose(fp); printf("Loading successful."); } Writing to file (just in case):
void write_to_file(const char *path, Book *first) { int i; printf("Saving...\n"); FILE *fp = fopen(path, "w"); Book* current = first; if (!fp) { printf("Error opening the file!"); dump_list(first); // Dumping the list to prevent memory leaks, this works okay } // Saving mechanism while (first != NULL) { for (i = 0; i < AK; i++) { fprintf(fp, "%s/", current->authors[i]); } fprintf(fp, "%s/%s/%u/%lf", current->title, current->publisher, ¤t->year, ¤t->price); fprintf(fp, "\n"); } fclose(fp); printf("Saved successfully"); }
new = new->next;: where do you give a value tonew->next?while (!feof(fp))is wrong: it tells you the last read did not fail but does not tell you the next read will not fail.typedef struct {...} Book;defines anonymous struct type, and typedefs it to type nameBook.struct Book *next;defines an opaque pointer to typestruct Book, which you never define (but this is ok, because it is a pointer and doesn't need to know the size). In general, avoidtypedefwith structs, because while it saves some typing, it also creates confusion (like demonstrated here).