Search code examples
arrayscstructansi-c

Why doesn't my array store the struct correctly?


I'm having quite a bit of trouble with something that should be really simple. In my program I have a struct called "Run":

typedef struct{
    char name[MAXNAMELENGTH], day[MAXDAYLENGTH];
    int distance, intDay;
    Date startDate;
    Time startTime;
    Time runTime;
} Run;

I parse data from a text file to this struct by using fgets() to parse a single line into an array called line[] and then call this function:

void parseTable(char line[NUMBEROFLINES], Run run, Run runs[NUMBEROFLINES], int *j){
    sscanf(line,"%s %s %s %d, %s %d:%d %d %d:%d:%d",run.name, run.day, run.startDate.month, &run.startDate.date, run.startDate.year,&run.startTime.hours, &run.startTime.minutes, &run.distance, &run.runTime.hours, &run.runTime.minutes, &run.runTime.seconds);
    runs[*j] = run;
    *j+=1;    
}

Now this function correctly assigns all the data to the struct run and stores that struct in the array runs[], but after this I wish to assign the struct a new value: intDay. For that I call upon the following function:

void dayToInt(Run run, Run runs[NUMBEROFLINES], int *i, int *a, int *b){
    if (strcmp(run.day,"Mon") == 0)
        run.intDay = 1;
    else if (strcmp(run.day,"Tue") == 0)
        run.intDay = 2;
    else if (strcmp(run.day,"Wed") == 0)
        run.intDay = 3;
    else if (strcmp(run.day,"Thu") == 0)
        run.intDay = 4;
    else if (strcmp(run.day,"Fri") == 0)
        run.intDay = 5;
    else if (strcmp(run.day,"Sat") == 0)
        run.intDay = 6;
    else if (strcmp(run.day,"Sun") == 0)
        run.intDay = 7;
    runs[*i] = run;
    *i += 1;
}

But this doesn't store the intDay value in my array runs[] and I really don't see why it doesn't. I've looked here and on other forums to see examples of how to do it but there must be something I keep missing, so if anyone can tell me what it is then it would be greatly appreciated :)


Solution

  • The issue here is "Pass-by-Value".

    When you call the function: void dayToInt(Run run, Run runs[NUMBEROFLINES], int *i, int *a, int *b){

    the first parameter, run, is actually copied into a local copy for the function. When you modify run.intDay, it only modifies the local copy.

    When you return from the function, all local modifications are lost, and the original structure, at the caller's scope, remains unchanged.

    To fix the problem, change the function to "Pass-by-Reference", meaning, pass a pointer to the struct you wish to change:

    void dayToInt(Run *prun, Run runs[NUMBEROFLINES], int *i, int *a, int *b){
        if (strcmp(prun->day,"Mon") == 0)
            prun->intDay = 1;
        else if (strcmp(prun->day,"Tue") == 0)
            prun->intDay = 2;
    [etc, etc]
    

    Edit On further inspection, it looks like the line:

    runs[*i] = run;
    

    should perform a copy of the structure, and preserve changes at the caller's scope. So I'm not sure why the changes to run.intDay are being lost. Investigating further.