2

我正在尝试拆分字符串并打印令牌。

int main()
{
    char line[255] = "182930101223, KLA1513";
    char val1[16];
    char val2[7];

    strcpy(val1, strtok(line, ","));
    strcpy(val2, strtok(NULL, ","));

    printf("%s|%s\n", val1, val2);

    return 0;
}

当我打印时,我得到

  3| KLA1513

代替

182930101223| KLA1513

问题是什么?

4

2 回答 2

7

好的,我认为这是一个无关的问题,但我现在认为这是您所看到的问题。

重要的是要记住 C 字符串比它们包含的多出 1 个字符。这是终止 NUL 字符 ( \0),并标记文本的结尾。

KLA1513实际上是 8 个字符 ( ) KLA1513\0。此外,因为您没有修剪空格,所以它是 9 个字符!_KLA1513\0(_ 是一个空格)。

这意味着您在第二次中超出了内存strcpy,导致未定义的行为,这(您将意识到)是您最糟糕的噩梦。

当您打印它时,谁知道程序处于什么状态。也许您覆盖的内存是print调用的一部分,或者它被再次覆盖并且现在var2没有终止。

只是var2变大(这里 9 个字符就足够了),以后使用安全的形式(strncpy例如)。像这样的错误是黑客通常设法破坏系统的方式。

于 2013-08-24T15:30:34.597 回答
2

尝试这个:

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

int main()
{
    char line[] = "182930101223, KLA1513";
    char* val1;
    char* val2;

    val1 = strtok(line, ",");
    val2 = strtok(NULL, ",");

    printf("%s|%s\n", val1, val2);

    return 0;
}

不需要strcpy()令牌,您可以使用char*; 将在找到的每个标记的末尾strtok()添加一个结束。\0

它也更安全,因为您不需要事先知道令牌的大小;你的令牌的大小是问题所在。如果您确实需要将令牌放在自己的内存中,您可以在之后将它们复制到足够大小的字符串中。

请注意,我们不能这样做:

char* line = "182930101223, KLA1513";

因为strtok()修改了字符串,并且不允许修改文字 C 字符串。

于 2013-08-24T15:33:16.167 回答