So i had an exam, and one of the excercies included to scan names from a binary file. I had used fscanf()
, but my prof told me that i cant use fscanf in binary file
I admit that I didn't find a way to explain what is wrong with fscanf()
and binary files that would be understood easily, but here is an example of how the binary
file generated is read erroneously by fscanf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Entry
{
char text[64];
int age;
};
int main()
{
FILE *file;
struct Entry entry;
file = fopen("data.bin", "wb");
if (file == NULL)
return -1;
entry.age = 30;
memset(entry.text, 0, sizeof(entry.text));
strcpy(entry.text, "Iharob Al Asimi");
fwrite(&entry, sizeof(entry), 1, file);
entry.age = 22;
memset(entry.text, 0, sizeof(entry.text));
strcpy(entry.text, "Claudio Urdaneta");
fwrite(&entry, sizeof(entry), 1, file);
entry.age = 29;
memset(entry.text, 0, sizeof(entry.text));
strcpy(entry.text, "Dayana Orozco");
fwrite(&entry, sizeof(entry), 1, file);
fclose(file);
file = fopen("data.bin", "rb");
if (file == NULL)
return -1;
fprintf(stderr, "with fscanf()\n");
/* this is intentionally == 1 to prove the point */
while (fscanf(file, "%63s%d", entry.text, &entry.age) == 1)
fprintf(stderr, "\t%s, %d\n", entry.text, entry.age);
rewind(file);
fprintf(stderr, "with fscanf()\n");
while (fread(&entry, sizeof(entry), 1, file) == 1)
fprintf(stderr, "\t%s, %d\n", entry.text, entry.age);
fclose(file);
return 0;
}
The problem is that fscanf()
will scan for text and match against the specifiers you pass to it.
But a binary file is just a bunch of bytes stored with a given structure, in the example above we write 64 + sizeof(int)
bytes per record, one of the items is just text so reading bytes with fscanf()
works as expected and it of course stops at the whitespace character.
But then the number has no text represantation in the file, and hence you cannot read it with fscanf()
.
Also, please note this
while (fscanf(file, "%63s%d", entry.text, &entry.age) == 1)
the correct way of doing it is
while (fscanf(file, "%63s%d", entry.text, &entry.age) == 2)
but then nothing will be printed because the integer wont be matched.
So when working with binary files you need
fread()
/fwrite()
whereas when the data is just text
fprintf()
/fscanf()
will be good.