Вопрос по parsing, malloc, text, strncpy, c – Мусор печатается при использовании strcpy

2

У меня есть функция, которая будет анализировать поступающие данные. Моя проблема в том, что после использования strncpy я получаю мусор, когда пытаюсь его распечатать. Я пытаюсь использовать malloc, чтобы сделать массив символов точного размера.

Код:

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

Ваш Ответ

5   ответов
1

Одна проблема: что, если нет новой строки?

Неопределенное поведение:

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

Источник и назначениеstrcpy не должно пересекаться

2

strncpy(data, pos + 2, (size_t)(pos2-pos)); не добавляет завершающий\0 символ в конце строки. Поэтому, когда вы попытаетесь распечатать его позже,printf() печатает всю строку данных и все, что находится в памяти, сразу после нее, пока не достигнет нуля - это тот самый мусор, который вы получаете. Вам необходимо явно добавить ноль в конце ваших данных. Это также необходимо дляatoi().

Edit: Вам нужно выделить еще один байт для вашегоdataи написать завершающий символ там.data[len_of_data] = '\0', Только после этого она становится допустимой строкой C, и вы можете использовать ее дляatoi() а такжеprintf().

Спасибо за ваш ответ. Как бы я добавил завершающий символ в конце? dead_jake
В основном вам нужно выделить еще один байт для вашегоdataи написать завершающий символ там.data[len_of_data] = '\0', Только после этого он становится строкой C, и вы можете использовать ее дляatoi() а такжеprintf().
Работает отлично сейчас! Спасибо dead_jake
2

чтобы он мог добавить ноль, когда вы выполняете strcpy (), но strncpy не будет добавлять ноль, так как для этого вам понадобится дополнительный байт.

5

strncpy не ставит нулевой символ в конце строки.

0

выделяя место для строки, чтобы добавить один байт для завершающего символа "\ 0". персонаж. Вы должны быть осторожны сstrncpyособенно если вы привыкли использоватьstrcpy, strcat, или жеsprintf, Эти три функции завершают строку с помощью «\ 0».strncpy копирует количество байтов, которое вы укажете, и не предполагает завершения строки.

Вы берете на себя эту ответственность, убедившись в том, что вы помещаете «\ 0». в конце буфера символов, в который вы скопировали. Это означает, что вы должны знать начальную позицию и длину копии и указывать «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.

[email protected]:~/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.
[email protected]:~/scratch$ 

Похожие вопросы