我正在逐行阅读一个文件,其中每行的格式为:
" number1 t number2".
我使用strtok和strncpy来分割,然后根据需要存储这两个值。然而,我发现在strncpy之后,number1被截断了一位数字。
你知道为什么会这样吗?怎么解决?
为简单起见,我硬编码了line_of_text来模拟这个问题。
谢谢!
代码:#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char line_of_text[80] = " 18306000 t 100n";
// NB: There's a t between the two values, the rest are spaces.
char* token;
int digits_per_num = 9;
char first_token[digits_per_num];
char second_token[digits_per_num];
token = strtok (line_of_text, "t");
printf("first token: %sn", token);
if (token != NULL)
{
strncpy (first_token, token, digits_per_num);
}
token = strtok (NULL, ",tn");
if (token != NULL)
{
strncpy (second_token, token, digits_per_num);
}
printf("first token copy: %sn", first_token);
printf("second token copy: %sn", second_token);
}
输出:first token: 18306000
first token copy: 1830600<junk>
second token copy: 100
第一个标记由10个字节组成:18306000
.
strncpy()
只在符合目标缓冲区的情况下写入空字符。但是你分配的字符太少了,所以它不能。
最简单的修复方法是在两个strtok调用的分隔符中包含空格:
token = strtok (line_of_text, " tn,");
我也建议使用snprintf()
而不是strncpy
,所以你总是保证在字符串的末尾得到一个空字符。
问题是缓冲区不够大;在这种情况下,strncpy
函数不会将缓冲区终止为空。
仅仅像你在评论中建议的那样增加缓冲区大小并不是一个健壮的解决方案,因为如果有人用更长的数字提供不同的输入,同样的问题将再次出现。
一个选项是手动终止缓冲区:
strncpy(first_token, token, digits_per_num);
first_token[digits_per_num - 1] = 0;
(注意:使用sizeof first_token
代替digits_per_num
也会更健壮)。
但是,在这种情况下,无效输入由静默截断处理。如果这不适合您的程序,那么您可以使用不同的逻辑,并完全避免不直观的strncpy
函数:
if ( strlen(token) + 1 > digits_per_num )
{
fprintf(stderr, "Error, input was more than 9 digitsn");
exit(EXIT_FAILURE);
}
strcpy(first_token, token);
strcpy
是安全的。