我有一个函数可以解析一些数据。我的问题是在使用strncpy后,当我尝试打印它时会得到一些垃圾。我尝试使用malloc使char数组具有确切的大小。
代码:
void parse_data(char *unparsed_data)
{
char *temp_str;
char *pos;
char *pos2;
char *key;
char *data;
const char newline = '\n';
int timestamp = 0;
temp_str = (char*)malloc(strlen(unparsed_data));
g_print("\nThe original string is: \n%s\n",unparsed_data);
//Ignore the first two lines
pos = strchr(unparsed_data, newline);
strcpy(temp_str, pos+1);
pos = strchr(temp_str, newline);
strcpy(temp_str, pos+1);
//Split the line in two; The key name and the value
pos = strchr(temp_str, ':'); // ':' divides the name from the value
pos2 = strchr(temp_str, '\n'); //end of the line
key = (char*)malloc((size_t)(pos-temp_str)-1); //allocate enough memory
data = (char*)malloc((size_t)(pos2-pos)-1);
strncpy(key, temp_str, (size_t)(pos-temp_str));
strncpy(data, pos + 2, (size_t)(pos2-pos));
timestamp = atoi(data);
g_print("size of the variable \"key\" = %d or %d\n", (size_t)(pos-temp_str), strlen(key));
g_print("size of the variable \"data\" = %d or %d\n", (size_t)(pos2-pos), strlen(data));
g_print("The key name is %s\n",key);
g_print("The value is %s\n",data);
g_print("End of Parser\n");
}
输出:
The original string is:
NEW_DATAa_PACKET
Local Data Set 16-byte Universal Key
Time Stamp (microsec): 1319639501097446
Frame Number: 0
Version: 3
Angle (deg): 10.228428
size of the variable "key" = 21 or 22
size of the variable "data" = 18 or 21
The key name is Time Stamp (microsec)
The value is 1319639501097446
F32
End of Parser
再次运行:
The original string is:
NEW_DATAa_PACKET
Local Data Set 16-byte Universal Key
Time Stamp (microsec): 1319639501097446
Frame Number: 0
Version: 3
Angle (deg): 10.228428
size of the variable "key" = 21 or 25
size of the variable "data" = 18 or 18
The key name is Time Stamp (microsec)ipe
The value is 1319639501097446
F
End of Parser
答案 0 :(得分:5)
您的结果是因为strncpy
没有在字符串的末尾添加空字符。
答案 1 :(得分:2)
你需要为一个字符串使用malloc()+1字节,所以当你执行strcpy()时它可以附加零,但是strncpy也不会附加零,你需要一个额外的字节。
答案 2 :(得分:2)
您的strncpy(data, pos + 2, (size_t)(pos2-pos));
未在字符串末尾添加终止\0
字符。因此,当您稍后尝试打印时,printf()
将打印出您的整个数据字符串及其后面的内存中的任何内容,直到它达到零 - 这就是您获得的内容。您需要在数据末尾显式附加零。 atoi()
也需要它。
修改强>
您需要为data
分配一个字节,并在那里写一个终止字符。 data[len_of_data] = '\0'
。只有在此之后它才会成为有效的C字符串,您可以将其用于atoi()
和printf()
。
答案 3 :(得分:1)
一个问题:如果没有换行怎么办?
未定义的行为:
pos = strchr(temp_str, newline);
strcpy(temp_str, pos+1);
strcpy
的来源和目的地不得重叠。
答案 4 :(得分:0)
你必须记住在为字符串分配空间时为终止'\ 0'字符添加一个字节。您必须小心使用strncpy
,特别是如果您习惯使用strcpy
,strcat
或sprintf
。这三个函数用'\ 0'终止字符串。 strncpy
复制您指定的多个字节,并且不假设终止字符串。
通过确保在复制的字符缓冲区末尾放置'\ 0'来承担责任。这意味着您必须知道复制的位置和长度,并将'\ 0'一个字节放在起始位置和长度的总和之上。
我选择以稍微不同的方式解决样本问题,但它仍然需要知道我复制的内容的长度。
在这种情况下,我使用strncpy
从pcszTestStr1
获取前9个字符
将它们复制到szTestBuf。然后,我使用strcpy - 以零结束字符串 -
附加句子的新部分。
#include <stdio.h>
#include <string.h>
int n;
int argv_2;
char szTestBuf[100] = {0};
char * pcszTestStr1 =
"This is a very long, long string to be used in a C example, OK?";
int main(int argc, char *argv[])
{
int rc = 0;
printf("The following sentence is too long.\n%s\n", pcszTestStr1);
strncpy(szTestBuf, pcszTestStr1, 9);
strcpy(szTestBuf + 9, " much shorter sentence.");
printf("%s\n", szTestBuf);
return rc;
}
这是运行test.c编译gcc -o test test.c
的输出。
cnorton@hiawatha:~/scratch$ ./test
The following sentence is too long.
This is a very long, long string to be used in a C example, OK?
This is a much shorter sentence.
cnorton@hiawatha:~/scratch$