将 strcpy() 与 strtok 一起使用
using strcpy() with strtok
我正在尝试拆分从文件中读入的行,然后使用 strcpy()
将我找到的数据复制到字符数组中 我知道 strcpy()
需要在末尾有一个空终止字符该行否则它将出现段错误,尽管我也尝试使用确定的缓冲区大小 strncpy()
以及 strncat()
并获得相同的结果。在我的代码片段中,我尝试在标记的末尾简单地添加一个空终止字符。
这是我失败的代码片段:
token = strtok(line, s);
strcpy(update, token);
token = strtok(NULL, s);
token = token + '[=10=]';
strcpy(firstName, token);
token = strtok(NULL, s);
此函数中的第一个 strcpy()
调用尚未失败。我第二次调用 strcpy()
每次尝试 运行 它都会失败。
我的其余代码可以找到here
strtok
returns 要么是空指针,要么是指向以 NUL 结尾的字节序列(即有效的 C 字符串)的指针。
您的 token = token + '[=13=]';
没有按照您(几乎可以肯定)的想法行事。由于 token
是一个指针(即来自 strtok
的 return 类型),它正在进行指针运算。幸运的是,'[=16=]'
是 0
的一种冗长的表达方式(暂时的琐事:C 中的字符文字具有类型 int
,而不是类型 char
),所以至少它没有改变指针。
检查 return 由 strtok
编辑的值。如果您的第二个 strcpy
失败,可能是因为 strtok
失败并且 return 空指针。
也就是说,如果您使用单个固定字符串来定义分隔符,那么使用 sscanf
可能会更轻松(也更干净)地完成这项工作。例如,如果 s
包含 ,.-+
,您可以使用:
sscanf(input, "%1[^,.-+]%*c%9[^,.-+]", update, firstname);
我暂时忽略了对 strtok
的第三次调用,因为您永远不会从其 return 值复制到目的地(但重复上述模式将适用于更多变量,当然)。注意 %
和扫描集 ([^...]
) 之间数字的使用。在使用 %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
的目标是一个问题,因为它总是附加一个尾随 '[=16=]'
来终止字符串。在这种情况下,您只分配了一个字符,因此您只有终止符的空间,而不是任何实际数据。您需要将其扩展到至少两个字符。鉴于您正在复制到固定大小的缓冲区,您可能想要在复制之前检查字符串是否适合您的缓冲区,或者使用一些限制复制数据大小的东西来复制(并且仍然总是包括一个终结符,不像 strncpy
).
复制前需要检查空指针。
token = strtok(line, s);
strcpy(update, token);
token = strtok(NULL, s);
//token = token + '[=10=]';
if(NULL != token)
{
strcpy(firstName, token);
token = strtok(NULL, s);
}
我正在尝试拆分从文件中读入的行,然后使用 strcpy()
将我找到的数据复制到字符数组中 我知道 strcpy()
需要在末尾有一个空终止字符该行否则它将出现段错误,尽管我也尝试使用确定的缓冲区大小 strncpy()
以及 strncat()
并获得相同的结果。在我的代码片段中,我尝试在标记的末尾简单地添加一个空终止字符。
这是我失败的代码片段:
token = strtok(line, s);
strcpy(update, token);
token = strtok(NULL, s);
token = token + '[=10=]';
strcpy(firstName, token);
token = strtok(NULL, s);
此函数中的第一个 strcpy()
调用尚未失败。我第二次调用 strcpy()
每次尝试 运行 它都会失败。
我的其余代码可以找到here
strtok
returns 要么是空指针,要么是指向以 NUL 结尾的字节序列(即有效的 C 字符串)的指针。
您的 token = token + '[=13=]';
没有按照您(几乎可以肯定)的想法行事。由于 token
是一个指针(即来自 strtok
的 return 类型),它正在进行指针运算。幸运的是,'[=16=]'
是 0
的一种冗长的表达方式(暂时的琐事:C 中的字符文字具有类型 int
,而不是类型 char
),所以至少它没有改变指针。
检查 return 由 strtok
编辑的值。如果您的第二个 strcpy
失败,可能是因为 strtok
失败并且 return 空指针。
也就是说,如果您使用单个固定字符串来定义分隔符,那么使用 sscanf
可能会更轻松(也更干净)地完成这项工作。例如,如果 s
包含 ,.-+
,您可以使用:
sscanf(input, "%1[^,.-+]%*c%9[^,.-+]", update, firstname);
我暂时忽略了对 strtok
的第三次调用,因为您永远不会从其 return 值复制到目的地(但重复上述模式将适用于更多变量,当然)。注意 %
和扫描集 ([^...]
) 之间数字的使用。在使用 %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
的目标是一个问题,因为它总是附加一个尾随 '[=16=]'
来终止字符串。在这种情况下,您只分配了一个字符,因此您只有终止符的空间,而不是任何实际数据。您需要将其扩展到至少两个字符。鉴于您正在复制到固定大小的缓冲区,您可能想要在复制之前检查字符串是否适合您的缓冲区,或者使用一些限制复制数据大小的东西来复制(并且仍然总是包括一个终结符,不像 strncpy
).
复制前需要检查空指针。
token = strtok(line, s);
strcpy(update, token);
token = strtok(NULL, s);
//token = token + '[=10=]';
if(NULL != token)
{
strcpy(firstName, token);
token = strtok(NULL, s);
}