I was learing File I/O in C and was interested in using it to read and write structures to files via fwrite()
and fread()
functions, now after my code ran successfully I was wondering if I could read a specific structure from an array of structures and put it in some given structure.
Here is my attempt at it
#include <stdio.h>
#include <stdlib.h>
typedef struct tools {
int recordno;
char toolname[50];
int quantity;
float cost;
} tools;
void recordprinter(tools a) {
printf("%d %s %d %f\n", a.recordno, a.toolname, a.quantity, a.cost);
}
int main() {
FILE * fp;
fp = fopen("file.txt", "rb+");
tools * a = (tools * ) malloc(100 * sizeof(tools));
for (int i = 0; i < 100; i++) {
a[i].cost = 0;
a[i].toolname[0] = 'a';
a[i].toolname[1] = '\0';
a[i].quantity = 0;
a[i].recordno = i + 1;
}
for (int i = 0; i < 100; i++) {
fwrite(a + i, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools), SEEK_CUR);
// I used fseek here just because fwrite doesnot move the cursor when\
it writes something to the file.(and fwrite(a + i, sizeof(tools), 100, fp) gives weird gliches)
}
fseek(fp, 0, SEEK_SET); // to bring cursor back to start of the file.
fread(a, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools) * 50, SEEK_SET); // now I expect the cursor to be at 51th structure.
fread(a + 3, sizeof(tools), 1, fp); // I am now writing the 51th structure in a[3]
recordprinter(a[3]);
// this gives output 26 and not 51
return 0;
}
Now when I ran the programm I expected 51 a 0 0.00000
as output,
but to my surprise it is picking up the 26th structure and putting it in a[3]
Any help will be appritiated!!
Try changing fopen
to use w+
instead of rb+
Also, remove the fseek
when creating the file, as mentioned, fwrite
definitely advances the file offset after writing data (provided fwrite
does write data at all).
Here is the output observed using the modified code below.
gcc main.c
./a.out
51 a 0 0.000000
// main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct tools {
int recordno;
char toolname[50];
int quantity;
float cost;
} tools;
void recordprinter(tools a) {
printf("%d %s %d %f\n", a.recordno, a.toolname, a.quantity, a.cost);
}
int main() {
FILE * fp;
// recommend for this example using w+
// w because it creates the file if the file doesn't exist
// r fails if the file doesn't exist (and that doesn't seem useful here)
// + because you are reading and writing
// avoiding b and choosing POSIX - linux
// may be wrong, if libc docs says b is needed then use b
// my doc "man fopen" says b is ignored
fp = fopen("file.txt", "w+");
// check return values, file pointer exist? fail if not
if (fp==NULL) { printf( "oops file not opened\n" ); return 1; }
tools * a = (tools * ) malloc(100 * sizeof(tools));
for (int i = 0; i < 100; i++) {
a[i].cost = 0;
a[i].toolname[0] = 'a';
a[i].toolname[1] = '\0';
a[i].quantity = 0;
a[i].recordno = i + 1;
}
// alternative way to save 100 objects
// if ( fwrite(a, sizeof(tools), 100, fp) != 100 )
// {
// printf( "oops 100 objects not written to file\n" );
// return 1;
// }
for (int i = 0; i < 100; i++) {
fwrite(a + i, sizeof(tools), 1, fp);
// remove fseek, not needed, fwrite does what is needed here
//fseek(fp, sizeof(tools), SEEK_CUR);
// I used fseek here just because fwrite doesnot move the cursor when
// it writes something to the file.(and fwrite(a + i, sizeof(tools), 100, fp) gives weird gliches)
}
// no review after this line, it seems to do what author intends
fseek(fp, 0, SEEK_SET); // to bring cursor back to start of the file.
fread(a, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools) * 50, SEEK_SET); // now I expect the cursor to be at 51th structure.
fread(a + 3, sizeof(tools), 1, fp); // I am now writing the 51th structure in a[3]
recordprinter(a[3]);
// this gives output 51 as desired
return 0;
}