0

在以下代码中:

#include <stdio.h>
#include <string.h>

int main (int argc, const char * argv[]) {

    char input[20];
    fgets(input, sizeof(input), stdin);
    char * pch;
    pch = strtok(input, " ");
    int i = 0;
    int nums[3];
    while (pch != NULL)
    {
        printf ("%s\n",pch);
        pch = strtok(NULL, " ");
        //nums[i] = atoi(pch);
        i++;
    }


    return 0;
}

的输入

1 2 3

给出:

1
2
3

当我取消注释注释行时,我得到:

1
2
3

Segmentation fault: 11

为什么这一行会导致段错误?

4

6 回答 6

5

最主要的是您需要在再次调用atoi(pch) 之前strtok运行:

printf ("%s\n",pch);
nums[i++] = atoi(pch);
pch = strtok(NULL, " ");

否则最后一次调用atoi将空指针作为参数传入并atoi崩溃。

另一个有趣的细节是input结尾可能包含换行符。这对 来说不是问题atoi,但它会导致您的循环迭代 4 次并在nums. 尽管它很可能不会导致您的程序崩溃,但这仍然是未定义的行为,您应该插入一个数组边界检查以防止它发生。

于 2013-05-23T07:56:24.820 回答
3

调试您的代码以使其正确和健壮。

技巧 1:避免原始数组中的无效内存访问

if (i >= 0 && i < 3)
{
   // The value of i is a Valid index for "int nums[3];"
   nums[i] = atoi(pch);
}
else
{
   // The value of i is NOT a Valid index for "int nums[3];", so why even try?
   // Using "nums[i]" here would cause undefined behaviour.
}

提示 2:缩小问题范围

int currentInt = atoi(pch);
nums[i] = currentInt;

这些线路中的哪一条正在崩溃?

如果是第二个,您应该能够通过我上面建议的范围检查来防止它。

如果它是第一个,int currentInt = atoi(pch);,这意味着 atoi 正在崩溃,因为它的返回值正好是 int,所以将它的结果分配给 currentInt 是安全的。

为什么atoi会崩溃?现在你已经缩小了你的问题。继续缩小范围,直到找到它。

于 2013-05-23T07:47:12.227 回答
1

保持换行

改变

pch = strtok(NULL, " ");

pch = strtok(NULL, " \n");
于 2013-05-23T07:48:03.817 回答
1

您必须检查 strtok 的返回(如果没有更多令牌则返回 NULL)并检查 i,因为此 var 不能达到 3,因为 nums 数组仅分配给 3 个 int。

while (pch != NULL && i < 3)
    {
        printf ("%s\n",pch);
        pch = strtok(NULL, " ");
        if (pch != NULL)
          nums[i] = atoi(pch);
        i++;
    }
于 2013-05-23T07:50:52.713 回答
0

因为你在数组边界外循环

int i = 0;
int nums[3];
while (pch != NULL)
{
    printf ("%s\n",pch);
    pch = strtok(NULL, " ");  
    nums[i] = atoi(pch);      // i == 3 will cause the issue
    i++;
}

而是尝试

int i = 0;
int nums[3];
for (pch = strtok(input, " "); pch != NULL && i < 3; pch = strtok(NULL," "))
{
    printf ("%s\n",pch);
    nums[i++] = atoi(pch); 
}
于 2013-05-23T07:52:08.737 回答
0

strtok每次使用您都会获得一个字符并将其放入数组中。
但是,strtok返回分隔符或字符串结尾之前的字符串。
对于最后一个值,即3,它还\n附加了一个,并且您试图将其作为单个字符放入。

只需在获取下一个值之前将值放入数组

int i = 0;
int nums[3];
while (pch != NULL)
{
    printf ("%s\n",pch);
    nums[i] = atoi(pch);
    pch = strtok(NULL, " ");
    i++;
}
/*// Testing the array
for(i = 0; i< 3; i++)
   printf("%d ",nums[i]);
*/
于 2013-05-23T07:55:50.047 回答