2015-04-26 2 views
0

Я выделяю пространство для узла struct в переменной n0. Я сохраняю эту структуру в файле с помощью fwrite, но многие говорят, что я сохраняю указатель на ustr. Но мне нужно сохранить строку ustr, Не могли бы вы помочь?Написание struct + сохранение только указателя?

typedef struct { 
    unsigned char * ustr; 
    int height; 
}node; 

void node_init(node * n, int r) { 

    int i; 
    n->ustr = malloc((r + 1) * sizeof(unsigned char)); 
    for (i = 0; i < r; i++) { 
     (n->ustr)[i] = random() & 0xff; 
    } 
    (n->ustr)[r] = 0; 
    n->height = -1; 
} 
void node_destroy(node * n) { 
    free(n->ustr); 
    n->height = -1; 
} 

int main() { 
    FILE* file_ptr = fopen("file1", "w+"); 
    node n0; 
    node_init(&n0,2); 
    fwrite(&n0, sizeof(node), 1, file_ptr); 
    fclose(file_ptr); 
    node_destroy(&n0); 
    return 0; 
} 
+0

Absolutelu '(n-> ustr) [i]', нет необходимости в круглых скобках. –

+0

Да, важно то, что 'sizeof (node)' недостаточно. И ваш код может очень легко вызвать неопределенное поведение. –

+0

добавить длину члена 'ustr' к' node' – BLUEPIXY

ответ

1

sizeof(node) неправильно, потому что он использует размер int и размер pointer, а не размер string. Вы должны либо выделить string, например, unsigned char ustr[10] или динамически выделять строку, но используйте символы, которые вы allocted, чтобы найти размер и указатель строки на fwrite.

Если вы статически выделить строку, это должно работать:

fwrite(&n0, sizeof(node), 1, file_ptr); 

В противном случае, если вы динамически выделять строку, вы должны сделать:

fwrite(&(n0 + sizeof(unsigned char *)), sizeof(int), 1, file_ptr); 
fwrite(n0.ustr, length_node, 1, file_ptr); 

или лучше:

fwrite(&n0.height, sizeof(int), 1, file_ptr); 
fwrite(n0.ustr, length_node, 1, file_ptr); 
+0

если длина определена #define length_node 3, во время компиляции Могу ли я использовать этот length_node? – Juan

+0

Вы имеете в виду 'unsigned char ustr [length_node + 1]'? Конечно. Я просто использую '+ 1' для' null byte' – nikaltipar

+0

, это возможно записать изменение fwrite (& n0, sizeof (node), 1, file_ptr); by fwrite (& n0, 2 * sizeof (int) + 2 * (unsigned char), 1, file_ptr) ;? – Juan

1

Я ответил на это и на ваш другой вопрос, но в основном, просто напишите два поля отдельно LY вместо того, чтобы писать все-структуру сразу:

int main() { 
    const int count = 2; 
    FILE* file_ptr = fopen("file1", "w+"); 
    node n0; 
    node_init(&n0,count); 
    /* write length of string so reader will know how much to read back */ 
    fwrite(&count, sizeof(count), 1, file_ptr); 
    fwrite(n0.ustr, count, 1, file_ptr); 
    fwrite(&n0.height, sizeof(n0.height), 1, file_ptr); 
    fclose(file_ptr); 
    node_destroy(&n0); 

    return 0; 
} 
+1

'strlen' может работать неправильно. Потому что он может содержать '0' для содержимого. '(n-> ustr) [i] = random() & 0xff;': 'random() & 0xff' может стать 0. – BLUEPIXY

+0

Хорошая точка, отредактированная для использования константы. –

+0

возможно записать изменение fwrite (& n0, sizeof (node), 1, file_ptr); by fwrite (& n0, 2 * sizeof (int) + 2 * (unsigned char), 1, file_ptr) ;? – Juan

1

Если число элементов ustr фиксируется во время компиляции, сделать его массив с таким количеством элементов, и не malloc() это. Это гарантирует, что будет записан массив, а не указатель.

Если длина строки НЕ фиксирована во время компиляции (например, интегральное значение, полученное от пользовательского ввода), - и вы хотите, чтобы она снова считывала структуру в другое время, используя fread(), и получить те же данные, которые были записаны, - тогда вам нужно будет сохранить длину в структуре и использовать два вызова fwrite() (первый должен будет сохранить длину, а второй должен будет вывести это количество символов). Например;

typedef struct 
{ 
    int height;   /* note change of order of member */ 
    int ustr_length; 
    unsigned char * ustr; 
} node; 

void node_init(node * n, int r) 
{ 
    int i; 
    n->ustr = malloc((r + 1) * sizeof(unsigned char)); 
    n->ustr_length = r+1;  /* save the length of u->str */ 
    for (i = 0; i < r; i++) { 
     (n->ustr)[i] = random() & 0xff; 
    } 
    (n->ustr)[r] = 0; 
    n->height = -1; 
} 
void node_destroy(node * n) 
{ 
    free(n->ustr); 
    n->height = -1; 
    n->ustr_length = 0; 
} 

int main() 
{ 
    FILE* file_ptr = fopen("file1", "w+"); 
    node n0; 
    node_init(&n0,2); 
    fwrite(&n0.height, 2*sizeof(int), 1, file_ptr); 
    fwrite(n0.ustr, n0.ustr_length, 1, file_ptr); 
    fclose(file_ptr); 
    node_destroy(&n0); 
    return 0; 
} 

Переводя это в код, который можно использовать fread() считывать данные обратно и восстановить исходную структура тривиальна.

Это действительно хорошая идея для проверки ошибок. malloc(), fopen(), fwrite(), fread(), и т. Д. Все могут не работать, и игнорировать это опасно.

+0

'fwrite (& n0.height, 2 * sizeof (int), 1, file_ptr);' Это неверно, если существует дополнение. – BLUEPIXY

+0

возможно записать изменение fwrite (& n0, sizeof (node), 1, file_ptr); by fwrite (& n0, 2 * sizeof (int) + 2 * (unsigned char), 1, file_ptr) ;? – Juan

+0

'fwrite (& n0.height, 2 * sizeof (int), 1, file_ptr);' -> 'fwrite (& n0.height, sizeof (int), 1, file_ptr); fwrite (& n0.ustr_length, sizeof (int), 1, file_ptr); – BLUEPIXY

Смежные вопросы