使用指针数组将struct保存到文件中

时间:2016-05-31 01:46:39

标签: c++ struct binaryfiles

我正在研究c ++,我需要将这个结构保存到文件中:

struct myStruct{
    int value;
    int value2;
    MyClass * myClass[10];
};

我保存此结构的方式如下:

myStruct my_struct;

my_struct.value = 1;
my_struct.value2 = 2;
for ( int i = 0; i < 10; i++){
    my_struct.myClass[i] = new MyClass();
} 

FILE* f = fopen(path.c_str(), "wb");

if ( f != NULL){

    fwrite(&my_struct, sizeof(myStruct), 1, f);
    fclose(f);
}

但是,当我想读取这个文件时,我的程序在尝试访问“MyClass”数组时崩溃了:

FILE* f = fopen(path.c_str(), "rb");

        if ( f != NULL){

            fread(&my_struct2, sizeof(struct myStruct), 1, f);
            fclose(f);
        }


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

            if ( my_struct2.myClass[i] != NULL ){

                //Here is the crash
            }
        }

我一直在寻找,但我找不到解决方案。我只找到有关结构数组的主题。我知道也许我的搜索不是很好。

感谢。

3 个答案:

答案 0 :(得分:1)

您的MyStruct包含指向其他结构的二十个指针。

通过fwrite()将MyStruct的内容添加到文件中,您已成功将其他结构的20个原始内存地址与{{{{}}的其他成员一起写入文件1}} class。

当你试图在另一个过程中阅读它们时,这当然是完全没有意义的。你已经回读了20个原始内存地址。这对完全不相关的过程毫无意义。并且,不出所料,访问这些内存地址会导致崩溃,因为这些内存地址,无论出于何种意图和目的,都是完全随机的值。

您的代码需要做的是不向文件写入20个原始指针地址,而是指向这些指针的内容以及它们指向的内容。

答案 1 :(得分:1)

我想在Sam的回答中添加一些内容,即使我知道这不是代码审查,你也是用C ++编写的。

C ++并不是用C语言编写的,它不希望......它一生都在努力打破其贬低父亲的束缚,超越他,探索新的意义和解决问题的方法,构建高效的代码。不要对他这样做......(顺便说一下,我喜欢C,显然不赞成这个笑话;)

我是这样做的:

#include <fstream>
#include <iostream>

class MyClass
{
public:
    MyClass() : _type(-1) {}
    MyClass(int type) : _type(type) {}

    inline const int    &type() const
    { return _type; }

private:
    int _type;
};

// -- overload of operator<< that permits me to write a MyClass* to a stream
std::ostream    &operator<<(std::ostream &stream, MyClass *myClass)
{
    stream << "myClass::type: " << myClass->type();
    return stream;
}

struct MyStruct
{
    int         value;
    int         value2;
    MyClass     *myClasses[10];

    MyStruct()
    {
        value = -1;
        value2 = 1;
        for (std::size_t i = 0 ; i < 10 ; ++i)
        { myClasses[i] = new MyClass(-i); }
    }
};

// -- overload of operator<< that permits me to write a MyStruct to a stream
std::ostream    &operator<<(std::ostream &stream, const MyStruct &myStruct)
{
    stream << "myStruct::"
            << "\n\t value: " << myStruct.value
            << "\n\t value2: " << myStruct.value2
            << "\n\t myClasses: ";
    for (std::size_t i = 0 ; i < 10 ; ++i)
    { stream << "\n\t\t " << myStruct.myClasses[i]; }
    return stream;
}

int main()
{
    std::ofstream outputFile("output.txt");

    if (outputFile.is_open() == false)
    { std::cerr << "Could not open file." << std::endl; return -1; }

    outputFile << MyStruct() << std::endl; // -- this is where the information is written into the file

    outputFile.close();
}

查看编写结构的简单方法,您甚至可以使用运算符&gt;&gt;以相同的方式将其返回到结构中重载,奖励是你可以在任何ostream上使用,这意味着它将适用于sstream,std :: cout和一切!

这仍然不是真正的c ++ - 就像有太多(不受保护的)指针和未经检查的神奇数字大小(MyClass *myClasses[10];这对我来说是禁忌,因为它意味着这件事:{{1}这个狗屎让我颤抖。

我可能会在这里使用std::array ,但我想按照你的定义保留MyStruct,这样的例子就会与你所写的内容保持“接近”。另一种方法是使用std::unique_ptrstd::shared_ptr

这可能看起来相当有点工作或令人生畏,但您可能会发现它在将来很有用。使用std容器(数组,集合,向量,映射等...),unique_ptr和shared_ptr也是如此。但我向你保证,值得花一些时间来理解它们并学习如何使用它们。它使事情变得更简单,更安全。

之前让我颤抖的是这样写的:

for (std::size_t i = 0 ; i < 10 ; ++i)

循环会像这样:

std::array<MyClass, 10> myClasses;

甚至更好,一种编写循环的c ++ 11方法,我觉得更容易读写:

for (std::size_t i = 0 ; i < myClasses.size() ; ++i)
{ myClasses[i].type(); }

for (std::array<MyClass, 10>::iterator itC = myClasses.begin() ; itC != myClasses.end() ; ++itC)
{ itC->type(); }

请注意,如果要修改myClass,请编写for (auto myClass : myClasses) { myClass.type(); }

希望它对你有所帮助。

答案 2 :(得分:0)

如果结构fwrite(&my_struct, sizeof(myStruct), 1, f);包含纯静态数据(即在编译时为其分配内存的数据),则使用my_struct是很好的。如果它包含动态数据(即在运行时为其分配内存的数据),则需要手动存储此类动态数据。 如图所示重载operator<<我的@vianney是一种保存/序列化动态数据的好方法。