Как записать в файл структуру с указателями?

308
03 декабря 2017, 13:36

Есть структура

struct  Data
{
    int iQuantLayer;            
    int* piQuantNInLayer;       
    double***pppdWeights;       
    double *pdIn;               
    double *pdOut;      
    double *pdBuff;             
};

Как записать её в файл таким образом, чтобы записались не адреса, а значения? С учетом того, что все указатели указывают на массивы.

Answer 1

Можно воспользоваться дедовским методом:

#include <stdio.h> // для FILE
#include <string>
struct  Data {
    std::string str;
    double *val;
};
int main() {
    Data *primary = new Data;
    primary->str = "TEST";
    primary->val = new double(99.99);
    FILE *fp;
    fp = fopen("buf.txt", "w");
    fwrite(primary, sizeof(Data), 1, fp); // запись.
    fseek(fp, 0, SEEK_END); // смещение в конец.
    fwrite(primary->val, sizeof(*primary->val), 1, fp); // запись содержимого указателя.
    fclose(fp);
    Data *secondary = new Data;
    fp = fopen("buf.txt", "r");
    fread(secondary, sizeof(Data), 1, fp); // чтение.
    secondary->val = new double; // выделяем новую память.
    fseek(fp, sizeof(Data), SEEK_SET); // смещение к началу содержимого указателя.
    fread(secondary->val, sizeof(*secondary->val), 1, fp); // чтение содержимого указателя.
    fclose(fp);
    // Проверка:
    if (std::strcmp(primary->str.c_str(), secondary->str.c_str()) == 0
        && *primary->val == *secondary->val)
    {
        // Ура! Все сошлось.
        return 0;
    }
    else {
        return 1;
    }
}

Извините, что упростил структуру. Но суть кода в следующем: записываем в файл содержимое структуры в бинарном виде; переходим в конец файла и записываем значение разыменовонного указателя; повторяем смещение и запись для всех указателей. Далее обратный процесс: читаем с начала файла структуру (указатели могут ссылаться уже на освобожденную память); выделяем новую память для указателей; смещаемся от начала файла на размер структуры; читаем объем по типу указателя; повторяем для всех указателей.

Answer 2
  1. Учитывая, что Вы используете массивы в C-стиле, то Вы должны где-то хранить кол-во элементов этого массива. На основании Вашего кода непонятно, где хранится это значение(-я). Потом это double***pppdWeights; - где инициализируется, как и т.п. Выкладывайте, пожалуйста, больше кода, иначе проблема может быть неясна.

  2. Далее, Вы пишете чтобы записались не адреса а значения.

    int * p = new int(10);
    std::cout << p << std::endl; // выводится адрес
    std::cout << *p << std::endl; // выводится значение
    

    Это был пример для указателя на int. Для массива будет как-то так:

    const std::size_t size = 10;
    int * array = new int [size];
    // ... - заполняем массив
    for (std::size_t i = 0; i < size; ++i)
        std::cout << array[i] << std::endl;
    
  3. Для вывода в файл вместо стандартного потока cout используете ofstream и выводите... Надеюсь, Вы знаете, как работать со стандартными потоками вывода.

Answer 3

У меня такое решение получилось

Использовал winapi

class LoaderNetw : public DataCl
    {
    public:
        LoaderNetw(Data *);
        ~LoaderNetw();
        int openNetw();
        void write();
        void read();
    private:
        void *file;
        unsigned char type = 0;
        unsigned char ch;
    };
int neural_network_lib::LoaderNetw::openNetw()
{
    std::exception e = std::exception("File it's open", 0);
    try
    {
        this->file = ::CreateFile(TEXT(url),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL);
        if (GetLastError() == ERROR_NOT_SUPPORTED)
            throw std::exception::exception("File not open", 1);
    }
    catch (const std::exception&e)
    {
        return 1;
    }

    return 0;
}
void neural_network_lib::LoaderNetw::write()    {
    ::SetFilePointer(this->file, 0, 0, FILE_BEGIN);
    DWORD fl = 0;
    ::WriteFile(this->file,
        &this->type, sizeof this->type, &fl, NULL);
    ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
    ::WriteFile(this->file, 
        &this->d->iQuantLayer, 
        sizeof this->d->iQuantLayer, 
        &fl, 
        NULL);
    for (int i = 0; i < this->d->iQuantLayer; i++) {
        ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
        ::WriteFile(this->file,
            &this->d->piQuantNInLayer[i],
            sizeof i,
            &fl,
            NULL);
    }
        for (int i = 1; i < this->d->iQuantLayer; i++)
            for (int j = 0; j < this->d->piQuantNInLayer[i]; j++)
                for (int k = 0; k < this->d->piQuantNInLayer[i - 1]; k++) {
                    ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
                    ::WriteFile(this->file,
                        &this->d->pppdWeights[i][j][k],
                        sizeof this->d->pppdWeights[i][j][k],
                        &fl,
                        NULL);
                }

}
void neural_network_lib::LoaderNetw::read() {
    DWORD fl = 0;
    ::SetFilePointer(this->file, 0, 0, FILE_BEGIN);
    ::ReadFile(this->file, &this->ch, sizeof this->ch, &fl, NULL);
    ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
    ::ReadFile(this->file,
        &this->d->iQuantLayer,
        sizeof this->d->iQuantLayer,
        &fl,
        NULL);
    for (int i = 0; i < this->d->iQuantLayer; i++) {
        ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
        ::ReadFile(this->file, &this->d->piQuantNInLayer[i], sizeof double(1), &fl, NULL);
    }
    for (int i = 1; i < this->d->iQuantLayer; i++)
        for (int j = 0; j < this->d->piQuantNInLayer[i]; j++)
            for (int k = 0; k < this->d->piQuantNInLayer[i - 1]; k++) {
                ::SetFilePointer(this->file, fl, 0, FILE_CURRENT);
                ::ReadFile(this->file,
                    &this->d->pppdWeights[i][j][k],
                    sizeof double(1),
                    &fl,
                    NULL);
            }
}
READ ALSO
Проблемы с проверкой подписи драйвера в Visual Studio

Проблемы с проверкой подписи драйвера в Visual Studio

Пытаюсь скомпилировать пример простейшего драйвера с MSDN:

234
Загрузка 3D моделей (Структура) C++ lib3ds

Загрузка 3D моделей (Структура) C++ lib3ds

Загружаю 3D модель с помощью lib3ds С++, в учебных целях питаюсь в консоль пропечатать все мешы материалы, всё что есть, но не получаеться по причине...

219
как добавить ссылку к проекту?

как добавить ссылку к проекту?

Пытаюсь использовать CUDA библиотеки от NVIDIA, все установилНужно к обычному проекту на c++ добавить ссылку на библиотеку из CUDA, но при добавлении...

288