Reputation: 21
I'm working on a simple library management system in C, where I need to add book details to a file. I’m using gets() to take input for the book name and author, but when I save the data into the file, I get unwanted null characters.
When I input the book name and author, I notice that extra null characters (\0) or spaces are being added when the data is saved to the file. The file content looks like it has unwanted padding between the fields (e.g., book name and author have extra spaces or null characters between them). The data seems correct when printed to the console, but when saved to the file, it includes these extra characters.
I used fflush(stdin) to clear the input buffer before using gets() to take input for the book name and author. I checked that the file is being opened in append mode (ab), and I’m writing the structure correctly using fwrite(). I have also considered that gets() is unsafe and should be avoided, but I used it based on the tutorial I followed. I’ve ensured that I’m using the correct format for the fwrite() function and the correct structure sizes with sizeof().
Program:
#include<stdio.h>
#include<stdlib.h>
struct books {
int id;
char bookName[50];
char authorName[50];
char date[12];
} b;
FILE *fp;
void addBook();
int main() {
int ch;
while (1) {
system("cls");
printf("<== Library Management System ==>\n");
printf("1. Add Book\n");
printf("0. Exit\n");
printf("Enter your choice: ");
scanf("%d", &ch);
switch (ch) {
case 0:
exit(0);
case 1:
addBook();
break;
default:
printf("Invalid Choice...\n");
}
printf("\nPress Any Key to Continue...");
getch();
}
return 0;
}
void addBook() {
fp = fopen("book.txt", "ab");
if (fp == NULL) {
printf("Error opening file!\n");
return;
}
printf("Enter Book ID: ");
scanf("%d", &b.id);
printf("Enter Book Name: ");
fflush(stdin);
gets(b.bookName); // I also tried fgets(), but the issue persists.
printf("Enter Author Name: ");
fflush(stdin);
gets(b.authorName);
fwrite(&b, sizeof(b), 1, fp);
fclose(fp);
printf("Book Added Successfully.\n");
}
I expected the binary file to contain only the fields that were written without any unnecessary padding or "NULL" entries.
Upvotes: 2
Views: 101
Reputation: 44339
Your expectations about fwrite
and binary files are wrong.
A line like:
fwrite(&b, sizeof(b), 1, fp);
will write a fixed number of bytes to the file no matter what value the members of b
have.
The number of bytes it will write is exactly sizeof(b)
- no more, no less.
On my system this code:
struct books b;
printf("%zu\n", sizeof b);
produces:
116
so for me 116 bytes will be written to the file.
Even if b.bookName
is a "short" string like e.g. "ABC" fwrite
will still write 116 bytes when saving b
to the file. The contents of the "extra bytes" of b.bookName
depends on what the program has been doing before the fwrite
.
You could try:
strcpy(b.bookName, "Pretty long but not too long string as bookname");
gets(b.bookName);
and then give a short input like "xyz". Then you'll see some of the "long" string in the binary file. But you'll also see a '\0'
after x
, y
, z
which tells where the real string value ends.
If you want to generate a file without "extra" bytes, don't use binary files and fwrite
. Take a look at fprintf
instead.
BTW: Notice that different systems may generate different binary files when executing the same C code. So in general you can't expect a binary file generated on one system to "work" on another system. In other words - if you want to use your data-files on different computer systems (e.g. big versus little endian), binary files is the wrong choice.
A few notes not directly related to the question:
gets
is something you shouldn't use. Use fgets
instead (and remember that fgets
may store newlines that you need to remove by additional code).
scanf
is also "problematic". Again consider fgets
and then do any parsing needed afterwards.
fflush(stdin)
isn't well-defined by the C standard so avoid it.
Upvotes: 6