C String拆分并打印令牌。

时间:2013-08-24 15:18:22

标签: c

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

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

问题是什么?

2 个答案:

答案 0 :(得分:7)

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

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

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

这意味着您在第二个strcpy中占用内存,导致未定义的行为,这将是您最糟糕的噩梦。

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

只需使var2更大(此处有9个字符就足够了),将来使用安全表单(例如strncpy)。像这样的错误是黑客通常设法破坏系统的方式。

答案 1 :(得分: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字符串。