I am using a binary file for reading an array of integers, then each even integer x should become 2 * x and each odd integer x should become 3 * x. When I am doing this it always read the 2nd integer (which is 2
). Any idea?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
f = fopen("inputData.txt", "w+b");
int n = 5;
int i;
for (i = 1; i <= n; ++i) {
fwrite(&i, sizeof(int), 1, f);
}
int x;
fseek(f, 0, SEEK_SET);
while (fread(&x, sizeof(int), 1, f) == 1) {
printf("%d ", x);
if (x % 2 == 0) {
fseek(f, -sizeof(int), SEEK_CUR);
x = x * 2;
fwrite(&x, sizeof(int), 1, f);
} else {
fseek(f, -sizeof(int), SEEK_CUR);
x = 3 * x;
fwrite(&x, sizeof(int), 1, f);
}
}
fclose(f);
}
w
truncates the file if it exists.+
does not change this behavior.Here is a simple demonstration.
Instead, use
r+b
.Two additional issues.
sizeof(int)
returns an unsigned number,size_t
. Your compiler will probably cast them to asigned long
for you, but should do that explicitly.You're not checking if your file operations succeeded. In this case they are, but they will silently fail and be difficult to debug. It's important to check all your file operations.
Okay, I don't really understand what's going on, but it seems that you cannot trust
fseek
withSEEK_CUR
when using with read/write files in that case (I'm running Windows, and the standard functions are notoriously different from Linux that may be the issue)EDIT: Andrew's answer confirms my suspicions. My solution complies to what the standards recommend.
What I have done to workaround the problem is to manage file position myself and seek to that position instead of implicitly relying on current file position when calling
fseek
.now the output of the program is (with current offset)
contents of the binary file is now (as expected on a little endian architecture):
So this is a workaround but at least it works properly.
This code:
violates the restrictions in 7.21.5.3 The fopen function, paragraph 7 of the C Standard (bolding mine):
Each loop iteration ends with an
fwrite()
call, and the next loop iteration starts withfread()
call, "without an intervening call to a file positioning function".