2009-04-14 87 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?序列化的數據不需要很漂亮。 :)