LINUX.ORG.RU

Запись структуры в файл


0

1

Вот кусок исходника:

struct dat
{
	int *c,*x,n;
};

....

	f=fopen("data.wtf","wb");
	int i,tmp;
	mas.n=StrToInt(Edit1->Text);
	mas.c=new int[mas.n];
	mas.x=new int[mas.n];
	for(i=0;i<mas.n;i++)
	{
		mas.c[i]=1;
		mas.x[i]=1;
	}
	fwrite(&mas,sizeof(mas),1,f);
	fclose(f);
При компиляции и выполнении никаких ошибок. Все отлично. Только при чтении с файла все mas.c и mas.x забиты не единицами, а нулями. Помогите.. В чем ошибка?

★★★

Последнее исправление: disee (всего исправлений: 1)

> StrToInt(Edit1->Text)

C-Builder допотопный какой-нибудь? ну и да - указатель на данные это не данные

aho
()
Ответ на: комментарий от Led

При чём тут линукс?

имхо концентрация пряморуких программистов под линуксом гораздо больше, нежели под виндой. Но это офтоп

disee ★★★
() автор топика
Ответ на: комментарий от aho

>C-Builder допотопный какой-нибудь? ну и да - указатель на данные это не данные

Borland Dev Studio. А какие варианты решения данной проблемы?

disee ★★★
() автор топика
Ответ на: комментарий от disee

>имхо концентрация пряморуких программистов под линуксом гораздо больше, нежели под виндой. Но это офтоп

Зачем ты разбавляешь эту концентрацию своим вендузячим присутствием?

Led ★★★☆☆
()
Ответ на: комментарий от disee

>А какие варианты решения данной проблемы?

добавь в структурку метод, который будет отвечать за запись данных в файл, а там записывай в файл n, далее в цикле каждый элемент c и x. ну и для считывания метод запили.

RedPossum ★★★★★
()

Во-первых, сериализация структур так не делается, ибо не переносимо, зависит не только от архитектуры процессора и системы, но зачастую и от компилятора. Во-вторых, когда вы передаете fwrite() для записи в файл указатель на структуру, он поля этой структуры в файл и запишет, т.е. в файл он положит значение указателей *c, *x и целочисленное значение n. А массивы вы выделяете в куче, они могут лежать вообще где угодно в пределах этой кучи. Как возможное решение, можно попробовать писать так:

fwrite((char *)mas.c, n*sizeof(int), 1, f); 
fwrite((char *)mas.x, n*sizeof(int), 1, f); 

hippi90 ★★★★★
()
Ответ на: комментарий от disee

А какие варианты решения данной проблемы?

Написать функции сериализации/десериализации для этой структуры.

Если ты просто дампишь эту dat, то у тебя записывается её бинарное представление в памяти, т.е. три слова, два из которых указатели (а куда?):

  то что пишет fwrite  | то что она не пишет
                       | (нужно писать ручками)
  ------------------------------------------------
  struct dat в памяти  | два "массива" в памяти
                       |
  ,-----------.
  | c | x | n |
  `-|---|-----^
    |   `--------------> [x[0], x[1], ..., x[n-1]]
    `------------------> [c[0], c[1], ..., c[n-1]]

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

Тоже самое относится и к функциям аллокации/освобождения памяти. Т.е. если структуры хоть сколько нибудь сложные (содержат указатели), то чтобы писать такого рода функции нужно вручную обходить такие структуры.

Вот пример:

/* TODO: error handling */

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int n, *a, *b;
} data_t;

/* Memory allocation/deallocation for `data_t' structures. */

data_t*
alloc_data_t(const int n)
{
    data_t *data;

    data    = (data_t*)malloc(sizeof(data_t));
    data->n = n;
    data->a = (int*)calloc(n, sizeof(int));
    data->b = (int*)calloc(n, sizeof(int));

    return data;
}

void
free_data_t(data_t *data)
{
    free(data->a);
    free(data->b);
    free(data);
    data = NULL;
}

/* Stream serialization/deserialization for `data_t' structures. */

void
put_data_t(FILE *stream, const data_t *data)
{
    fwrite(&data->n, sizeof(int), 1, stream);
    fwrite(&data->a, data->n * sizeof(int), 1, stream);
    fwrite(&data->b, data->n * sizeof(int), 1, stream);
}

data_t*
get_data_t(FILE *stream)
{
    int n;
    data_t *data;

    fread(&n, sizeof(int), 1, stream);

    data = alloc_data_t(n);

    fread(&data->a, n * sizeof(int), 1, stream);
    fread(&data->b, n * sizeof(int), 1, stream);

    return data;
}

/* File serialization/deserialization for `data_t' structures. */

void
save_data_t(const char *fn, const data_t *data)
{
    FILE *f;

    f = fopen(fn, "wb");
    put_data_t(f, data);
    fclose(f);
}

data_t*
load_data_t(const char *fn)
{
    FILE *f;
    data_t *data;

    f = fopen(fn, "rb");
    data = get_data_t(f);
    fclose(f);

    return data;
}

/* Printer for `data_t' structures. */

void
print_data_t(const data_t *data)
{
    int i;

    printf("%i, [%i", data->n, data->a[0]);

    for(i = 1; i < data->n; i++)
        printf(", %i", data->a[i]);

    printf("], [%i", data->b[0]);

    for(i = 1; i < data->n; i++)
        printf(", %i", data->b[i]);

    printf("]\n");
}

/* Usage example. */

int
main()
{
    int i;
    data_t *d1, *d2;

    d1 = alloc_data_t(10);

    for(i = 0; i < 10; i++) {
        d1->a[i] = i;
        d1->b[i] = i * i;
    }

    print_data_t(d1);

    save_data_t("data.bin", d1);

    print_data_t(d1);

    d2 = load_data_t("data.bin");

    print_data_t(d2);

    save_data_t("data2.bin", d2);

    print_data_t(d2);

    free_data_t(d1);
    free_data_t(d2);    

    return 0;
}
quasimoto ★★★★
()
mas.c=new int[mas.n];
...
fwrite(&mas,sizeof(mas),1,f);

А чему по вашему равен sizeof(mas)? Неужели sizeof(mas) == mas.n + mas.n + other_members + align?

andreyu ★★★★★
()

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

Для исключения проблем с различными версиями компиляторов и ОС лучше подстелить соломки и писать еще размер поля, при чтении сравниваться и выкидывать ошибку если не совпало.

AIv ★★★★★
()
Ответ на: комментарий от anonymous

это просто отнехероделать поделие, ясен хрен это опенсорс! Че он продавать будет какую то свою программу, неумеючи даже сериализовать данные.... я против бана

pozitiffcat ★★★
()
Ответ на: комментарий от quasimoto

Спасибо большое. Все проблемы решены :)

disee ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.