使用strcpy时打印垃圾

我有一个函数可以解析一些数据。我的问题是在使用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 

你的strncpy(data, pos + 2, (size_t)(pos2-pos)); 不会在字符串的末尾添加终止\0字符。 因此,当您稍后尝试打印时, printf()打印您的整个数据字符串以及它后面的内存中的任何内容,直到它达到零 – 这就是您获得的结果。 您需要在数据末尾显式附加零。 atoi()也需要它。

编辑:您需要为数据分配一个字节,并在那里写一个终止字符。 data[len_of_data] = '\0' 。 只有在它之后它才会成为有效的C字符串,你可以将它用于atoi()printf()

您的结果是因为strncpy没有在字符串的末尾添加空字符。

你需要为一个字符串使用malloc()+1字节,所以当你执行strcpy()时它可以附加零,但是strncpy也不会附加零,你需要一个额外的字节。

一个问题:如果没有换行怎么办?

未定义的行为:

 pos = strchr(temp_str, newline); strcpy(temp_str, pos+1); 

strcpy的源和目标不能重叠。

您必须记住在为字符串分配空间时为终止’\ 0’字符添加一个字节。 你必须小心strncpy ,特别是如果你习惯使用strcpystrcatsprintf 。 这三个函数用’\ 0’终止字符串。 strncpy复制您指定的多个字节,并且不假设终止该字符串。

您可以通过确保在复制的字符缓冲区末尾放置一个’\ 0’来承担这一责任。 这意味着您必须知道复制的位置和长度,并将’\ 0’一个字节放在起始位置和长度的总和之外。

我选择以稍微不同的方式解决样本问题,但它仍然需要知道我复制的内容的长度。

在这种情况下,我使用strncpypcszTestStr1获取前9个字符并将它们复制到szTestBuf。 然后,我使用strcpy – 用零结束字符串 – 来附加句子的新部分。

 #include  #include  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$