简体   繁体   English

使用fgets和strtok从文件读取和解析行

[英]Reading and parsing lines from a file with fgets and strtok

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. 我需要从下面显示的文件中读取每一行,使用strtok将其分为3个部分,并将每个部分存储到一个数组中。 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. 由于某些原因,nameArray [0-9]都包含“ Tarasenko”,对此将提供任何帮助。

You didn't copy out the name, you just put the pointer returned by strtok into your data structure. 您没有复制名称,只是将strtok返回的指针放入数据结构中。 You are just ending up with a data structure full of identical pointers to the same memory pointed to by buffer . 您最终将得到一个数据结构,该数据结构包含指向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. 由于buffer的内容在每次循环中都会被修改,因此最终会得到一堆指向最后一次指针的指针。

strtok returns a pointer to a null-terminated string containing the next token. strtok返回指向包含下一个标记的以空值终止的字符串的指针。 To actually copy this token, you should use strcpy : 要实际复制此令牌,应使用strcpy

strcpy(names[i],    strtok(buffer,      " \n"));
strcpy(goals[i],    atoi(strtok(NULL,   " \n")));
strcpy(assists[i],  atoi(strtok(NULL,   " \n")));

Also note that there is a memory leak in your code: 另请注意,您的代码中存在内存泄漏:

void readLinesFromFile(/*...*/)
{
    char * buffer = malloc(MAX_LINE*sizeof(char));
    // ...
    fgets(buffer, MAX_LINE, fPtr);
    // ...
}

You dynamically allocate the buffer by calling malloc , but you don't free this memory. 您可以通过调用malloc动态分配buffer ,但不会释放此内存。 Don't forget to call free() on a pointer pointing to the memory that has been allocated by malloc . 不要忘记在指向malloc分配的内存的指针上调用free() But in this case, the array with automatic storage duration would be a better choice: 但是在这种情况下,具有自动存储持续时间的阵列将是一个更好的选择:

void readLinesFromFile(/*...*/)
{
    char buffer[MAX_LINE];
    // ...
    fgets(&buffer, MAX_LINE, fPtr);
    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM