2012-06-22 109 views
0

我有一個函數可以解析一些進入的數據。我的問題是使用strncpy後,當我嘗試打印它時,我得到一些垃圾。我嘗試使用malloc使char數組具有確切的大小。使用strcpy時正在打印垃圾

代碼:再次

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 

運行它:

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 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 

回答

1

您的strncpy(data, pos + 2, (size_t)(pos2-pos));不會在字符串末尾添加終止的\0字符。因此,當您稍後嘗試打印時,printf()會打印整個數據字符串以及其後的所有內容,直到達到零 - 這就是您所獲得的服飾。您需要在數據末尾顯式附加零。它也需要atoi()

編輯: 您需要爲您的data分配了一個多字節,寫一個終止字符那裏。 data[len_of_data] = '\0'。只有在它成爲一個有效的C字符串,你可以使用它爲atoi()printf()

+0

感謝您的回覆。我如何在末尾添加終止字符? –

+0

基本上你需要爲你的'data'分配一個字節,並在那裏寫一個終止字符。 'data [len_of_data] ='\ 0''。只有在它之後它變成了一個C字符串,你可以將它用於'atoi()'和'printf()'。 – Alex

+0

現在完美工作!謝謝 –

5

你的結果是,因爲strncpy不會在字符串的結尾放一個空字符。

1

一個問題:如果沒有換行符怎麼辦?

未定義行爲:

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

的來源和目的地strcpy必須不重疊。

2

對於一個字符串,你需要malloc()+1字節,所以它可以在你執行strcpy()時追加零,但是strncpy不會追加零,你需要一個額外的字節。

0

您必須記住爲字符串分配空間來爲終止'\ 0'字符添加一個字節。您必須小心strncpy,尤其是如果您習慣於使用strcpystrcatsprintf。這三個函數用'\ 0'結束字符串。 strncpy複製您指定的字節數,並且不假定終止字符串。

您通過確保在複製的字符緩衝區末尾放置'\ 0'來承擔責任。這意味着你必須知道開始的位置和複製的長度,並把'\ 0'一個字節超過起始位置和長度的總和。

我選擇稍微不同地解決示例問題,但它仍然涉及知道我複製的長度。

在這種情況下,我使用strncpypcszTestStr1和 中的前9個字符複製到szTestBuf。然後,我使用strcpy - 以0結尾字符串 - 來追加句子的新部分。

#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的輸出。

​​