首页 > 解决方案 > 我需要帮助以连续方式将对象的字段正确写入文件

问题描述

我正在做一个项目,该项目基本上将我创建的一些对象的字段数据的内容写入文件(其中一个是 PERSON 类的 pers1);

我已将数据插入到对象 pers1 的字段成员中,并打开了一个文件,尝试使用 file.write 函数将这些字段成员(字符串名称、姓氏和无符号整数年龄)的内容写入文件。它写了部分内容,中间有很多垃圾。请帮我编写正确的代码,以便我可以将每个人的详细信息连续写入文件。谢谢

   #include<iostream>
    #include<string>
    #include<fstream>
    #include <sstream>
    #include <iomanip>
    #include <list>

    class PERSON
    {
        string name;
        string surname;
        unsigned int age;
    public:
        void inputinfo()
        {
            cin>>name;
            cin>>surname;
            cin>>age;
        }
        outputinfo()
        {
            cout<<name;
            cout<<surname;
            cout<<age;
        }
    };

    class STUDENT: public PERSON
    {
        int ID;
        float marks_sum;
        string belonging_class;
    public:
        inputinfo()
        {
            cin>>name;
            cin>>surname;
            cin>>age;
            cin>>ID;
            cin>>marks_sum;
            cin>>belonging_class;
        }
    };

    void writeinfile()
    {
        PERSON pers1;
        ofstream file1
        file1.open("Students.txt", std::ofstream::out | std::ofstream::app);
        pers1.inputinfo();
        file1.write(pers1.c_str(),pers1.length()); // this is the second aproach I've found on internet, but it gives errors;
        file1.write((char*)&pers1, sizeof(pers1)); // this one is puting alot of garbage into the file, alongside fields data.
        fisier.close();
    }

    int main
    {
        int opt1, opt2;
        char option;

        switch(opt1)
        {
        case 1:
            do
            {
                cout<<endl;
                        <<"Choose one of variants"<<"1.Students"<<"2.Teachers"<<"3.Get back to main menu"<<endl;
                cin>>opt2;
                switch(opt2)
                {
                case 1:
                    do
                    {
                        cout<<"Do you wish to introduce a new student(Y/N)?";
                        cin>>option;
                        if(option!='N')
                            writeinfile()
                    } while(option!='N');
                            break;
                    default:
                        cout<<"Incorect!"<<endl;
                    }
                    while(opt2!=3);
                    break;
                case 2: "...."
                    ;
                    break
                case 3: "...."
                    ;
                    break;
                }
            }
        }

每次调用上述函数时,我都希望将字段数据干净地写入文件中。例如对于第一次迭代,当我在对象的字段中输入数据时:姓名:John,姓:Doe,年龄:45,我希望在文件中看到这些数据(并且中间没有垃圾)。

标签: c++ofstream

解决方案


#include <iostream>
#include <fstream>

std::ostream& operator<< (std::ostream& os, const PERSON& value )
{
    // here, you decide how the output format should look like. See below.
    // ...
    return os;
}

std::istream& operator>> (std::istream& is, PERSON& value )
{
    // here, you do the reverse of what you chose in operator<<(). See below.
    // ...
    return is;
}

虽然您将能够快速破解这两个功能的实现,但值得考虑您想要完成的要求:

  • 维护?当您更改您的 PERSON(例如额外的字段)时,您的文件将来会发生什么?您还希望能够使用那些旧文件吗?
  • 稳健性。您是否必须注意本地化?如果你的第一个中国学生带着汉字名字到达会发生什么?你需要utf8编码还是类似的?你会遇到“缺失值”吗?
  • 可扩展性?您最终会用自己的 SQL 编写自己的小数据库,以便稍后查询人员子集吗?一旦文件超出预期,您还能阅读整个文件吗?带有其他数据的新文件是否会到达,以后是否需要关联它们?(外连接,内连接,...)

正如您从这个简短且肯定不完整的列表中看到的那样,您正处于十字路口:改用数据库?使用标准的序列化格式,如 XML 或 JSON 或协议缓冲区或 FastNProto 或当今流行的任何东西?或者只是继续做你自己的事情,因为它无论如何都是一件快速而肮脏的事情?

现在,到实际的事情:

在你的内部operator<<,你可以像这样“转储”你的元素(坚持你在问题中写的):

os << "name: " << value.name.c_str() 
   << ", surname: " << value.surname.c_str() 
   << ", age: " << value.age 
   << std::endl;

并将其读回,您operator>>相应地实施。

std::string tag;
is >> tag; // optionally make sure it is "name:"
is >> value.name;
// ... (The commas might need some fiddling... well you wanted help not a full solution...)

然后,您需要做的就是对其进行测试,例如使用字符串流、序列化一个人、将其读入另一个实例并进行比较。你应该完成了;)


推荐阅读