使用strcpy()和strtok

时间:2016-04-09 00:17:09

标签: c segmentation-fault strcpy strcat

我正在尝试从文件中分割读入的行,并使用strcpy()将我找到的数据复制到字符数组中我明白strcpy()在行尾需要一个空终止字符否则它会出现故障,尽管我也尝试使用确定的缓冲区大小strncpy()以及strncat()具有相同的结果。在我的代码片段中,我尝试在令牌末尾添加一个空终止字符。

这是我失败的代码片段:

    token = strtok(line, s);
    strcpy(update, token);
    token = strtok(NULL, s);
    token = token + '\0';
    strcpy(firstName, token);
    token = strtok(NULL, s);

此功能中的第一个strcpy()调用尚未失败。我第二次调用strcpy()时每次尝试运行它都会失败。

我的其余代码可以找到here

2 个答案:

答案 0 :(得分:3)

复制前需要检查空指针。

token = strtok(line, s);
strcpy(update, token);
token = strtok(NULL, s);
//token = token + '\0';
if(NULL != token)
{
    strcpy(firstName, token);
    token = strtok(NULL, s);
}

答案 1 :(得分:0)

strtok返回空指针或指向NUL终止字节序列的指针(即有效的C字符串)。

你的token = token + '\0';并不是在做你(几乎可以肯定)的想法。由于token是一个指针(来自strtok的返回类型),它正在进行指针运算。幸运的是,'\0'是一种冗长的说法0的方式(当前的琐事:C中的字符文字类型为int,而不是类型char),所以至少它没有改变指针。

检查strtok返回的值。如果您的第二个strcpy失败,可能是因为strtok失败并返回空指针。

也就是说,鉴于您使用单个固定字符串来定义分隔符,您可以使用sscanf更轻松地(更干净地)完成工作。例如,如果s包含,.-+,您可以使用:

sscanf(input, "%1[^,.-+]%*c%9[^,.-+]", update, firstname);

我暂时忽略了对strtok的第三次调用,因为您永远不会将其返回值复制到目的地(但重复上述模式当然会适用于更多变量,当然)。请注意使用%和扫描集([^...])之间的数字。 总是想要在使用%s或%[...] . The size you specify should always be one smaller than the buffer into which you're having them write (because they always append a trailing' \ 0'`)时指定缓冲区的大小。

如果s实际上是您从外部来源读取的字符串(或该订单中的某些内容,因此您无法轻松将其内容放入字符串文字中),那么您可以合成如果需要,在运行时格式化字符串:

char template[] = "%%[^%s]%%*c%%[^%s]";
char format[512];

sprintf(format, template, s, s);
sscanf(input, format, update, firstname);

[虽然格式字符串通常是文字,但不是必需的。]

编辑:我认为您最初没有链接代码,但它至少会发现一个问题:char update[1];。将此作为strcpy的目标是一个问题,因为它总是附加一个尾随'\0'来终止字符串。在这种情况下,您只分配了一个字符,因此您只有终结器的空间,而不是任何实际数据。您需要将其扩展为至少两个字符。鉴于您要复制到固定大小的缓冲区,您可能希望在复制之前检查字符串是否适合您的缓冲区,或者使用复制的内容来限制它复制的数据大小(并且始终包含终止符,与strncpy不同。