我目前在C“{”method“:”emptyFood“,”params“:”08:00 09:00 10:00“}中有一个名为'json'的字符串
并尝试将时间提取为3个不同的变量。
for(int i = 0; i<5; i++)
{
ts1[i] = json[i+32];
}
for(int j = 0; j<5; j++)
{
ts2[j] = json[j+38];
}
for (int k = 0; k<5; k++)
{
ts3[k] = json[k+44];
}
printf("time1 = %s\n", ts1);
printf("time2 = %s\n", ts2);
printf("time3 = %s\n", ts3);
如果我同时打印它们,我会得到这样的奇怪输出
time1 = 08:009:010:00
time2 = 09:010:00
time3 = 10:00
但是,如果我逐个打印它们,它会为每个打印语句打印出正确的时间。
我究竟做错了什么?
C中的字符串以空值终止。这意味着字符串以空字节结尾。 (字符串中的一个字节的类型为char
。)当您将子字符串的字节复制到新的字节数组时,您正在复制字符串的“有用”内容,但要获得完整的字符串,您还需要写空终止符。例如:
for(int i = 0; i<5; i++)
{
ts1[i] = json[i+32];
}
ts1[5] = 0;
(不要混淆空字节0
,也可以写成'\0'
,用数字'0'
。)
写一个更惯用的方式就是这样
memcpy(ts1, json + 32, 5);
ts1[5] = 0;
复制子字符串的设计更好的函数是strlcpy
但不幸的是它不是标准C的一部分,所以许多平台都没有它。请注意,strncpy
不能很好地完成这项工作,因为它不会在您的情况下写入空字节。
请注意,您需要6个字节来存储5个字节的字符串,即您必须声明char ts1[6]
或char *ts1 = malloc(6)
(或更大的数字)。
当你逐个打印字符串时它似乎工作的原因是在内存中的字符串之后必须有一个空字节。这只是一个巧合,如果函数是从不同的地方调用,如果它之前的代码处理不同的数据,如果使用不同的编译器编译,等等,可能不会发生。鉴于你得到的三个变量的输出,必须有什么发生的事情是编译器碰巧把ts1
,ts2
和ts3
以及其他碰巧在内存中连续出现空字节的东西。因此,当您尝试打印ts1
时,该地址处的字符串会在ts1
,ts2
和ts3
上运行,最后在该空字节处停止。有一个空字节只是运气的一击,或者可能是因为它隐藏了关于missing null terminator的错误而中风。