2

入ってくるデータを解析する関数があります。私の問題は、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
4

5 に答える 5

5

結果はstrncpy、文字列の末尾にヌル文字を配置しないためです。

于 2012-06-22T17:57:52.337 に答える
2

文字列に対してmalloc()+1バイトを使用する必要があるため、strcpy()を実行するとゼロが追加されますが、strncpyはゼロを追加しないため、追加のバイトが必要です。

于 2012-06-22T18:01:21.693 に答える
2

文字列の末尾にstrncpy(data, pos + 2, (size_t)(pos2-pos));終了文字を追加しません。\0したがって、後で印刷しようとすると、printf()データ文字列全体とその直後のメモリにあるものはすべて、ゼロになるまで印刷されます-それがガーベートです。データの末尾にゼロを明示的に追加する必要があります。にも必要ですatoi()

編集: にもう 1 バイトを割り当てdata、そこに終了文字を書き込む必要があります。data[len_of_data] = '\0'. その後、有効な C 文字列になり、 および に使用できatoi()ますprintf()

于 2012-06-22T18:06:25.733 に答える
1

1 つの問題: 改行がない場合はどうなるでしょうか。

未定義の動作:

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

のソースと宛先がstrcpy重複してはなりません。

于 2012-06-22T17:59:42.413 に答える
0

文字列にスペースを割り当てる際に、終端の '\0' 文字に 1 バイトを追加することを覚えておく必要があります。特に、、またはのstrncpy使用に慣れている場合は注意が必要です。これら 3 つの関数は、文字列を '\0' で終了します。指定したバイト数をコピーし、文字列の終了を想定しません。 strcpystrcatsprintfstrncpy

コピー先の文字バッファーの末尾に '\0' を必ず配置することで、その責任を負います。つまり、コピーの開始位置と長さを把握し、開始位置と長さの合計の 1 バイト後に '\0' を配置する必要があります。

サンプルの問題を少し異なる方法で解決することを選択しましたが、コピーしたものの長さを知る必要があります。

この場合、strncpy最初の 9 文字pcszTestStr1を 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$ 
于 2012-06-23T16:48:50.260 に答える