2009-04-14 122 views
2

我最近才了解到C++类的friend关键字和序列化的用法,现在我需要一些帮助才能使其工作。C++类序列化

我没有问题序列化我的类到一个文件,它的工作很好,但是我很难试图读取这个文件到一个向量容器。我敢肯定,我需要在我的代码循环逐行阅读,但由于类有不同的类型,我想我不能使用std :: getline(),也许这种方法不会使用istream方法我实施? 样本输出文件将是:

Person 1 
2009 
1 

Person 2 
2001 
0 

我的代码:

class SalesPeople { 
    friend ostream &operator<<(ostream &stream, SalesPeople salesppl); 
    friend istream &operator>>(istream &stream, SalesPeople &salesppl); 

    private: 
     string fullname; 
     int employeeID; 
     int startYear; 
     bool status; 
}; 

ostream &operator<<(ostream &stream, SalesPeople salesppl) 
{ 
    stream << salesppl.fullname << endl; 
    stream << salesppl.startYear << endl; 
    stream << salesppl.status << endl; 
    stream << endl; 
    return stream; 
} 

istream &operator>>(istream &stream, SalesPeople &salesppl) 
{ 
    stream >> salesppl.fullname; 
    stream >> salesppl.startYear; 
    stream >> salesppl.status; 
    // not sure how to read that empty extra line here ? 
    return stream; 
} 

// need some help here trying to read the file into a vector<SalesPeople> 
SalesPeople employee; 
vector<SalesPeople> employees; 

ifstream read("employees.dat", ios::in); 
if (!read) { 
    cerr << "Unable to open input file.\n"; 
    return 1; 
} 

// i am pretty sure i need a loop here and should go line by line 
// to read all the records, however the class has different 
// types and im not sure how to use the istream method here. 

read >> employee; 
employees.push_back(employee); 

顺便说一句,我知道Boost库有很大的序列化类,但是我在努力学习如何系列化现在可以使用STL库。 非常感谢您为我提供的任何帮助以及让我走上正轨!

回答

2

它看起来像你几乎拥有所有你需要的代码!我复制了你的代码,并对它进行了一些修改,以便从循环中的文件中读取SalesPeople。我将包括下面的更改,但由于这是用于作业,所以在查看代码之前,您可能只想阅读并思考以下提示。

  • 对于在 循环阅读的销售员,我会建议您采取 看看这个FAQ。它有一个 的例子,几乎正是你需要的 。我相信FAQ 15.4也会帮助 你。

  • 有关如何从文件中读取 当处理 多余的空行,看看这个 link你的问题。您可以非常简单地通过 这种方式提取空白。

  • 由于jfclavette的建议,我会 建议考虑 std::getline在 销售人员的全名阅读,因为你需要 在该行的一切到一个 字符串。

虽然我有一个问题,那么employeeID呢?我注意到它在示例代码中被忽略。这是故意的吗?

现在,如果你还需要帮助,你可以看看我写的让代码这个工作:

istream &operator>>(istream &stream, SalesPeople &salesppl) 
{ 
    //stream >> salesppl.fullname; 
    getline(stream, salesppl.fullname); 
    stream >> salesppl.startYear; 
    stream >> salesppl.status; 
    // not sure how to read that empty extra line here ? 
    stream >> ws; 
    return stream; 
} 

while(read >> employee) 
{ 
    // cout << employee; // to verify the input, uncomment this line 
    employees.push_back(employee); 
} 

而且,jfclavette建议,它可能不是一个坏主意,添加一些输入验证(从它读取后检查流状态并验证它仍然是好的)。虽然我会推荐使用while()循环,原因在于FAQ 15.5中陈述的原因。

+0

非常感谢你!!!! 这帮了很多!现在我明白我做错了什么更好。 另外,我对ws一无所知,我一直在想如何做很久!非常感谢! – nmuntz 2009-04-15 00:29:35

1

不知道你的问题是什么。你究竟有什么不了解?你的名字由多个标记组成的事实?没有办法做到这一点,你可能想通过getline()获得名称。或者,您可能想要在序列化并读取适当的令牌计数时指定令牌的数量。即你的文件可能看起来像。

2人1

我以为,人是第一个名字和1姓氏在这里。你也可以强制这样的概念,即有一个名字和一个姓氏,然后分别阅读每一个。

您通常会在(!ifstream.eof())和循环中循环。当然,你应该始终验证输入。

另外,你为什么要在每条记录之间添加额外的endl?序列化的数据不需要很漂亮。 :)