1

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 :)

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Goibon
  • 251
  • 3
  • 17

2 Answers2

2

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.

abelenky
  • 63,815
  • 23
  • 109
  • 159
  • I see that @GWW also provided the same answer, then deleted it. I'd love to know why? – abelenky Nov 30 '11 at 18:05
  • Thanks a lot :) but when I call upon the function dayToInt like so: dayToInt(runs[i], runs, &i, &a, &b) I get "error: incompatible type for argument 1 of ‘dayToInt’", any idea why? – Goibon Nov 30 '11 at 18:34
  • The proper call would be dayToInt(&runs[i], runs......) (take the ADDRESS-OF the first parameter). See my **Edit**: I'm not sure this will solve your problem, and I'm still not sure what is going on. – abelenky Nov 30 '11 at 19:13
  • unfortunately it still doesn't seem to save the struct to the array :( I really thought your suggestion would work because it made so much sense to send it as a pointer. Do you think that I would be able to send the struct local to dayToInt() to another function by calling the next function from within dayToInt() ? **Edit**: Turns out I can :) I guess that's my temporary solution for now then. – Goibon Nov 30 '11 at 19:49
0

Your code works.

So, either your trouble lies in how you call the function, or on how you check that it works (do you check the correct element of the array, i.e. the one before the current value of i, which on return has just been incremented?)

ninjalj
  • 42,493
  • 9
  • 106
  • 148
  • I call the function and print the intDay from the struct in a loop like so: `while(i – Goibon Nov 30 '11 at 19:55
  • @Saaru: so you are always printing the same `run`. – ninjalj Nov 30 '11 at 20:06
  • Try `printf("%d",runs[i-1].intDay);` – ninjalj Nov 30 '11 at 20:07
  • Now that I look at it.. I change the value of i inside the function dayToInt, and then after I come back to the loop I call upon the print function but by then I am at the next index in the array. I must be an idiot :P – Goibon Nov 30 '11 at 20:11
  • @Saaru: you shouldn't increment `i` inside the function. As you have seen, it's counter-intuitive and error-prone. `i` belongs to the function calling `daysToInt`, and should be modified there. – ninjalj Nov 30 '11 at 20:26