Question

I have spent quite a lot time attempting to find a solution how to write and read structure to/from file and completely get stuck.

The code should be very simple, but I think I've missed quite important details about fwrite/fread. I think write is working but I am not completely sure. Once I try to read into array I get segmentation fault error on the k=1.

I would be ultimately happy if someone could guide me in what direction should I move further.

#include <stdio.h>

struct Student {
char matrikl[6];
char shortName[6];
int value1;
int value2;
int value3;
int value4;
int money;
}xStudent;

int calcMoney(int,int,int,int);

int main(void)
{
int i=0;
printf("How much students to insert!\n");
scanf("%i",&i);
    struct Student S[i];

for (int var = 0; var < i; ++var) {
    printf("insert student data\n");
    printf("Matriklinumber\n");
    scanf("%s", S[var].matrikl);
    printf("Student name\n");
    scanf("%s", S[var].shortName);
    printf("Insert values!\n");
    scanf("%i%i%i%i",&S[var].value1,&S[var].value2,&S[var].value3,&S[var].value4);
    S[var].money=calcMoney(S[var].value1,S[var].value2,S[var].value3,S[var].value4);;
}

FILE*sourcefile;
sourcefile=fopen("text.txt","ab+");

for (int var = 0; var < i; ++var) {
    fwrite(&S[var],sizeof(struct Student),1,sourcefile);
}
fclose(sourcefile);


sourcefile=fopen("text.txt","rb+");
struct Student A[i];

if (sourcefile==NULL) perror ("Error opening file");
          else
          {
                  int k=0;
                  while (fgetc(sourcefile) != EOF) {
                  fread(&A[k],sizeof(struct Student),1,sourcefile);
                  k++;
                  }
          }
fclose(sourcefile);
return 0;
}

int calcMoney(int xvalue1, int xvalue2, int xvalue3, int xvalue4)
{
int Sum = xvalue1+xvalue2+xvalue3+xvalue4;
if(Sum==20)
    return 100;
else
    if(Sum>=16 && Sum<20)
        return 75;
    else return 0;
}
Was it helpful?

Solution

You have the right idea, but this should fix your problem.

for (int var = 0; var < i; ++var) {
    fwrite(&S[i], sizeof(struct Student), 1, sourcefile);
}

The argument 1 in fwrite after the sizeof statement indicates you only want to add one Student at a time.

Please see the doc for fwrite: http://www.cplusplus.com/reference/cstdio/fwrite/

And also:

          while (fgetc(sourcefile) != EOF) {
          fread(&A[k], sizeof(struct Student), 1, sourcefile);
          k++;
          }

Please see the doc for fread: http://www.cplusplus.com/reference/cstdio/fread/

I know it's the cplusplus website, but it's the only place I could find good docs on the functions.

Also, the below array initializes to 0 elements:

struct Student A[k];

You may want to try managing a linked list for this instead.

Might end up looking something like:

struct StudentList {
    struct Student* student;
    struct StudentList* next;
};


struct StudentList* students = NULL;

while(!feof(sourcefile)) {
    struct StudentList* newlink = malloc(sizeof(struct StudentList));
    newlink->student = malloc(sizeof(struct Student));
    newlink->next = NULL;

    fread(newlink->student, sizeof(struct Student), 1, sourcefile); 

    if(NULL != students) {
        struct StudentList* iter;
        for(iter=students;
            NULL != iter->next;
            iter = iter->next); // iterate to last link

        iter->next = newlink; // add new link to the end
    } else students = newlink; // add new link to the beginning
}



Then to free your list, just use something like:

struct StudentList* iter, *head;
for(iter=students;
    NULL != iter;)
{
    head = iter;
    free(iter->student);
    free(iter);
    iter = head;
}

OTHER TIPS

the error is in the declaration of array A.

struct Student A[k];

k=0; so you are getting error since A[1] or so the array is not defined. change the declaration to

struct Student A[i];

then it should run if rest of code and syntax is fine.

Fix fwrite line to:

fwrite(&S[i], sizeof(struct Student), 1, sourcefile);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top