Определение строки C неизвестной длины - PullRequest
1 голос
/ 01 мая 2011

Мне нужно хранить данные (ранее неизвестного формата / размера) внутри строки для последующей обработки (для хранения в файле XML)

Как мне это сделать?

Как видите, приведенный ниже код сгенерирует segfault.

char * type;
char * output;

for (i=0; i< 10; i++){ 

if(strcmp(GTK_OBJECT_TYPE_NAME(g_hash_table_lookup(widgetbuffer,allocate[i])), "GtkAdjustment") == 0){
    type = "spin";
    sprintf(output, "%f", gtk_adjustment_get_value(GTK_ADJUSTMENT(g_hash_table_lookup(widgetbuffer,allocate[i]))));

}else if(strcmp(GTK_OBJECT_TYPE_NAME(g_hash_table_lookup(widgetbuffer,allocate[i])), "GtkCheckButton") == 0){
    type = "check";
    sprintf(output, "%d", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_hash_table_lookup(widgetbuffer,allocate[i]))));

}else if(strcmp(GTK_OBJECT_TYPE_NAME(g_hash_table_lookup(widgetbuffer,allocate[i])), "GSList") == 0){
    type = "radio"; // Loop through grouped buttons and find active one
    sprintf(output, "%d", g_slist_position(g_hash_table_lookup(widgetbuffer,allocate[i]),
                g_slist_find_custom(g_hash_table_lookup(widgetbuffer,allocate[i]),
                    NULL, (GCompareFunc) searchRadio)));

}else if(strcmp(GTK_OBJECT_TYPE_NAME(g_hash_table_lookup(widgetbuffer,allocate[i])), "GtkComboBox") == 0){
    type = "combo";
    sprintf(output, "%d", gtk_combo_box_get_active(GTK_COMBO_BOX(g_hash_table_lookup(widgetbuffer,allocate[i]))));

}else if(strcmp(GTK_OBJECT_TYPE_NAME(g_hash_table_lookup(widgetbuffer,allocate[i])), "GtkEntry") == 0){
    type = "entry";
    output = (char *) gtk_entry_get_text(GTK_ENTRY(g_hash_table_lookup(widgetbuffer,allocate[i])));

}
[...]

Ответы [ 4 ]

4 голосов
/ 01 мая 2011

Как правило, для «хранения данных неизвестного размера» в строке C у вас есть два варианта:

  1. Выделите достаточно большой буфер для хранения любого ожидаемого размера (что означает, что вы урежете данные, если он превысит этот размер), или

  2. Динамически выделить буфер (используя malloc()), который достаточно велик для хранения данных. Не забудьте также free()

В вашем коде используется неинициализированный указатель output, и поэтому он является ошибочным. Вам нужно будет сделать одно из вышеперечисленного.

2 голосов
/ 02 мая 2011

Если на вашей платформе есть snprintf или аналогичный (у большинства есть), то вам нужно что-то вроде этого:

int n = snprintf( NULL, 0, "%s is %d", somestring, someinteger );
char * p = malloc( n + 1 );
sprintf( p, "%s is %d", somestring, someinteger );

Первый вызов snprintf возвращает количество символов, необходимых для хранения отформатированного вывода, но на самом деле не делает никакого форматирования.Затем вы выделяете необходимое пространство и выполняете реальное форматирование.

2 голосов
/ 01 мая 2011

Вы не выделяете output, и именно поэтому вы получаете ошибки сегментации. Как и в приведенном коде, output не было инициализировано. Ваш компилятор должен предупредить вас об этом.

Если вы знаете безопасный максимальный размер, вы можете просто разместить его в стеке:

char output[512];

... если максимальный размер был 512 байт. В противном случае вы можете посмотреть на malloc, чтобы выделить память из кучи.

0 голосов
/ 02 мая 2011

В дополнение к предварительному выделению достаточно большого буфера или усечению вывода до размера:

  1. Предварительно обработайте генерацию (без записи, просто посчитайте длину) и выделите подходящий буфер длявторой (действительно записываемый) проход
  2. Запись в «неограниченное» хранилище: файл
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...