Reading and parsing lines from a file with fgets and strtok

user2100887 picture user2100887 · Feb 22, 2013 · Viewed 7.9k times · Source

I'm having trouble with a fairly basic bit of code. I need to read each line from the file shown below, split it up into the 3 parts with strtok, and store each part into an array. The arrays for "goals" and "assists" are working perfectly, but for some reason the entire name array is filled with the last name read from the file.

Input file:

Redden 2 0
Berglund 5 2
Jackman 2 0
Stewart 4 0
Oshie 3 5
McDonald 2 4
Pietrangelo 2 7
Perron 2 6
Tarasenko 5 5

Relevant code:

int main(int argc, char* argv){  
    FILE* inFile = fopen(argv[1],"r");
    char ** nameArray;
    int * goalArray;
    int * assistArray;
    int size = countLinesInFile(inFile);
    allocateMemory(&goalArray, &assistArray, &nameArray, size);
    readLinesFromFile(inFile, goalArray, assistArray, nameArray, size);
}

void allocateMemory(int** goals, int** assists, char*** names, int size)
{
  *goals = malloc(size*sizeof(int));
  *assists = malloc(size*sizeof(int));
  *names = malloc(size*sizeof(char *));
  int i;
  for(i=0; i<size; i++)
  {
    *(*names + i) = calloc(MAX_NAME,sizeof(char));
  }
}

void readLinesFromFile(FILE* fPtr, int* goals, int* assists, char** names, int numLines)
{
  int i;
  char * buffer = malloc(MAX_LINE*sizeof(char));
  for(i = 0; i<numLines; i++)
  {
    if(fgets(buffer, MAX_LINE, fPtr)!= NULL)
    {
      names[i] = strtok(buffer, " \n");
      goals[i] = atoi(strtok(NULL, " \n"));
      assists[i] = atoi(strtok(NULL, " \n"));
    }
  }
}

For some reason, nameArray[0-9] all contain "Tarasenko", and any help with this would be greatly appreciated.

Answer

Carl Norum picture Carl Norum · Feb 22, 2013

You didn't copy out the name, you just put the pointer returned by strtok into your data structure. You are just ending up with a data structure full of identical pointers to the same memory pointed to by buffer. Since the contents of buffer get modified on every pass through the loop, you end up with a bunch of pointers to whatever it was the last time through.