1

Im a beginner in C. I would like to write and read a binary file, and i reached this so far:

I can my struct to a binary file, and can read.

Problem one: I can only read integers, somehow strings are printed as garbage or random characters.

Problem two: If i run my program, i add some entries to my binary file, then i print all the entries it is working fine (except Problem one), but after i terminate my program and run AGAIN i got Segmentation Fault while i try to read the file.

Please help me, i just cannot move forward.

/* Our structure */
struct rec
{
    int max,cost;
    char *name;
};


struct rec addNewEntry()
{

    //init
    char name[256];
    int max;
    int cost;

    //input
    printf("Type name: \n");
    scanf("%s" , &name) ;

    printf("Type guests limit: \n");
    scanf("%d", &max);

    printf("Type price: \n");
    scanf("%d", &cost);

    //create record
    struct rec record;

    record.name = name;
    record.max = max;
    record.cost = cost;

    return record;

}

int main()
{

    FILE *ptr_myfile;


    //////////////////////////MENU////////////////////////////////

    int option=-1;


    while(option!=3)
    {

        printf("\n=== MENU === \n");
        printf("\n1. Print all entries");
        printf("\n2. Add new entry");
        printf("\n3. Exit");
        printf("\n");

        printf("\nType menu option:");

        scanf("%d", &option);


        if(option == 1)
        {
            printf("\n...Printing all entries\n");



            int f=open("stadionok.db",O_RDONLY); 
            if (f<0){ perror("Error at opening the file\n");exit(1);}

             struct rec my_record; 

             while (read(f,&my_record,sizeof(my_record))){ //use write for writing
                printf("name: %s  \n",my_record.name);
                printf("max: %d  \n",my_record.max);
                printf("cost: %d  \n",my_record.cost);
             } 


            close(f);


        }
        else if(option ==2)
        {

            printf("\n...Type a new entry\n");


            //OPEN AND CHECK
            ptr_myfile=fopen("stadionok.db","a");
            if (!ptr_myfile)
            {
                printf("Unable to open file!");
                return 1;
            }

            //TYPE A NEW ENTRY
            struct rec new_stad = addNewEntry();

            //WRITE TO FILE
            fwrite(&new_stad, sizeof(struct rec), 1, ptr_myfile);


            //CLOSE
            fclose(ptr_myfile);

            printf("Done.\n");
        }


    }   




    return 0;
}

E D I T:

I modified just as you suggested and now i got: error: incompatible types in assignment

at:

char name[256];


//input
printf("Type name: \n");
scanf("%s" , &name) ;


struct rec record;

record.name = name; //HERE
2
  • 1
    name is already an address so no need to prefix it with &. you cannot assign an array to another array like that. use memcpy or strncpy to copy the contents of the array. Commented Mar 24, 2014 at 21:52
  • Thanks that worked verry well. Commented Mar 24, 2014 at 21:57

1 Answer 1

2

The reason you get garbage strings is that you are writing a char pointer into the file. The simple way to do what you want is to use a char array with a fixed length inside your struct. like so:

struct rec
{
    int max,cost;
    char name[1024];
};

It is also the reason for the crash. When you read the data and trying to print the string the printf() probably tries to read from a memory block that is not valid, because the memory addresses changed.

If you want to write strings with dynamic size into the file it gets a bit more complicated.
Then you should not write the struct itself, but the values of it and the size of the string.
PseudoCode Example:

write(max);
write(cost);
write(strlen(name)); // strlen + 1 if you want to include \0
write(name);

max = readInt();
cost = readInt();
nameLen = readInt();
allocatememory(nameLen);
name = read_n_bytes(namelen);


To your edit: if rec.name is still a pointer (char*) you have to assign a pointer to it, not an array.

rec.name = &name;

if your rec.name is an array with a fixed size now:

strncpy(rec.name, name, sizeof(rec.name)); // copy the string to rec.name
rec.name[strlen(name)] = '\0'; // add a binary 0 to the end of the string

Note: if you are reading more than 1 struct (in a loop), you should not use char name[256];, because every rec.name would be pointing to name which is overwritten everytime you read a new value. Use the following construct for every entry:

char* name; //define name as a pointer
name = malloc(256); // allocate a new memory block and assign a pointer to it to name
scanf("%s" , name); // No & needed because name is already a pointer
rec.name = name; // No & needed because name is already a pointer
Sign up to request clarification or add additional context in comments.

1 Comment

see my edit. I also corrected an error on my side. printf crashes because it want to access a memory address which is not valid anymore

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.