views:

94

answers:

2

Hello, I have a lot of data stored in bin format as a sequence of structs. I want to be able to read randomly any of the structs and modify it in C. I am trying with the following code but it doesn't work. Can someone fix it for me please?

Also, would it be possible to delete an intermediate struct from the file in between?

The code is below:

#include <stdio.h>
#include <stdlib.h>

struct rec {
        int x,y,z;
};

void f_rite()
{
        int i;
        FILE *ptr_myfile;
        struct rec my_record;

        ptr_myfile=fopen("test.bin","w");

        for ( i=0; i < 5; i++ ) {
                my_record.x = i;
                fwrite( &my_record, sizeof(struct rec), 1, ptr_myfile );
        }

        fclose(ptr_myfile);

        return;
}


void f_read()
{
        int i;
        FILE *ptr_myfile;
        struct rec my_record;

        ptr_myfile=fopen("test.bin","r");

        for ( i=1; i <= 5; i++) {
                fread(&my_record,sizeof(struct rec),1,ptr_myfile);
                printf("%d\n",my_record.x);
        }
        printf("\n");

        fclose(ptr_myfile);

        return;
}

void f_rerite()
{
        int i;
        FILE *ptr_myfile;
        struct rec my_record;

        ptr_myfile=fopen("test.bin","rw");

        for ( i=5; i >= 0; i-- ) {
                fseek( ptr_myfile, sizeof(struct rec)*i, SEEK_SET );
                fread( &my_record, sizeof(struct rec), 1, ptr_myfile );
                my_record.x = my_record.x + 100;
                fwrite( &my_record, sizeof(struct rec), 1, ptr_myfile );
        }

        fclose(ptr_myfile);

        return;
}

int main()
{
        f_rite();
        f_read();
        f_rerite();
        f_read();

        return 0;
}
+2  A: 

"rw" is wrong. Use "r+". Don't forget to seek back after reading.

Ignacio Vazquez-Abrams
Thanks a lot! :) But why is seek back important? Even without that it seems to be working fine? :(
Without the seek it would actually be modifying the *next* struct in the file.
Ignacio Vazquez-Abrams
Ok, I was wrong. Just corrected it. Thanks all again. :)
+2  A: 

There is no "rw" flag to fopen. You need "r+" for reading and writing(updating). Since it's binary data, you should actually use "r+b" , and "wb" in your f_rite function and "rb" in your f_read function. Also:

  • Check the return value of calls that could fail, you'd discover that e.g. fwrite failed.
  • Your f_rerite functions iterates through 6 elements, you're off by one.
  • Your f_rerite also writes to the next element. Likely you want to update the current record rather. Which means you need to fseek again after calling fread.
nos
OP doesn't say what platform he's on, but I think "rb" and "r+b" are Microsoft extensions that won't apply to other platforms.
Dewayne Christensen
I have tried it on RHEL 5.3 and they work as OB has said. :)
the 'b' flags are standard C, although on *nixes this typically have no effect as the system doesn't handle binary/text files differently.
nos