1

所以我对 C 编程很陌生,并且遇到了一个我真的不明白的问题。我正在从文件中读取行,并尝试将每一行(作为字符串)存储在一个数组中。然后我在该行上使用 strtok 来解​​析行外的另一个值。出于某种原因,在我使用 strtok 后,我放入数组中的值发生了变化。代码如下:

while(fgets(readLine, 100, inFile) != NULL) { 
    printf("j = %d\n", j);
    puts(readLine); 
    machineList[j] = readLine;
    puts(machineList[j]); //the value of machineList[j] at this point is equal
                          // to the current readLine 

    int i=0;

    day = strtok(readLine, " ,");

    puts(machineList[j]); //the value of machineList[j] at this point is no
                          //longer what it was at the previously noted point

    while(i<3) {
        day=strtok(NULL, " ,");
        i++;
    }
    dayList[j]=atoi(day);

    printf("Day is: %d\n\n", dayList[j] );  //these values come out as expected
    j++;

}

谁能解释为什么会这样?我不明白,因为它不像我重新分配 machineList[j]=readLine。因此,即使 readLine 的值发生变化,它也不应该改变 machineList[j] 中的值。再说一次,我是 C 的新手,所以我意识到我的代码语义可能很糟糕——任何事情都有帮助。谢谢!

4

3 回答 3

1

strtok通过用空字节替换分隔符来修改原始字符串。

我假设machineList是一个指向 的指针数组char,所以这是:

machineList[j] = readLine;

...machineList[j]指向readLine. 然后这个:

day = strtok(readLine, " ,");

...modifies readLine,它也修改,machineList[j]因为它指向它。您需要制作一个副本:

// allocate machineList[j]
strcpy(machineList[j], readLine);

如果你不复制,当你的while循环结束时,machineList基本上是一个悬空指针数组。

于 2013-02-04T20:02:06.740 回答
1

你的问题在这里

machineList[j] = readLine;

这不会整个 char 字符串复制到machineList[i],而只是将引用(指针、内存地址)复制到readLine。因此,如果您修改readLine,machineList[j]仍将引用此修改后的字符串。

如果要复制字符串,请使用strcpy()

strcpy(machineList[j], readLine);

machineList如果没有(复制之前) ,请不要忘记分配内存:

machineList[i] = malloc(strlen(readLine) + 1);

恢复:

machineList[i] = malloc(strlen(readLine) + 1);
strcpy(machineList[j], readLine);

或者,正如 Arkadiy 指出的,用strdup()一句话将分配和复制结合起来:

machineList[i] = strdup(readLine);

完成后,不要忘记释放内存:

free(machineList[i]); // For each i
于 2013-02-04T20:02:31.893 回答
0
while(fgets(readLine, 100, inFile) != NULL) { 
    printf("j = %d\n", j);
    puts(readLine); 

考虑一下,这里的地址readLine是 0x1234abcd。

    machineList[j] = readLine;

现在,machineList[j]包含值(因此指向)0x1234abcd

    puts(machineList[j]); //the value of machineList[j] at this point is equal
                          // to the current readLine 

所以,你会得到正确的答案。

    int i=0;

    day = strtok(readLine, " ,");

不幸的是,这里 0x1234abcd 的值发生了变化(因为发生了readLine变化)。记住, 0x1234abcdmachineList[j]指向readLine哪个地址

    puts(machineList[j]); //the value of machineList[j] at this point is no
                          //longer what it was at the previously noted point

:-(不幸的是,您会得到不需要的结果。

相反,您可以使用strdup()(不是 STDC)在内存中创建一个新字符串,复制其中的数据readLine并返回指向内存的指针。

或者,您可以通过首先malloc()ing 字符串,然后使用strcpy()

于 2013-02-04T20:09:20.190 回答