2009-09-01 28 views
-1

我從文件中讀入while循環不會中斷。我不確定問題是什麼。如果您需要更多信息,請詢問。文件循環和讀入地圖的問題

代碼:

#include <string> 
#include <map> 
#include <fstream> 
#include <iostream> 
#include <iterator> 

using namespace std; 

class Customer { 
public: 
    string name; 
    string address; 
    Customer() {} 
}; 

class Purchase { 
public: 
    string product_name; 
    double unit_price; 
    int count; 
    Purchase() {} 
    Purchase(string pn, double up, int c) :product_name(pn), unit_price(up), count(c) {} 
}; 

// Function Object for comparison in map container 
struct Cmp_name { 
    bool operator()(const Customer& first, const Customer& second) 
    { return first.name < second.name; } 
}; 

// ostream overloads 
ostream& operator<<(ostream& out, const Customer& c) 
{ 
    out << c.name << '\n' 
     << c.address << '\n'; 
    return out; 
} 

ostream& operator<<(ostream& out, const Purchase& p) 
{ 
    out << p.product_name << '\n' 
     << p.unit_price << '\n' 
     << p.count << '\n'; 
    return out; 
} 

istream& operator>>(istream& in, Customer& c) 
{ 
    getline(in, c.name); 
    getline(in, c.address); 
    return in; 
} 

istream& operator>>(istream& in, Purchase& p) 
{ 
    getline(in, p.product_name); 
    in >> p.unit_price >> p.count; 
    return in; 
} 

int main() 
{ 
    cout << "Enter file to read orders from: \n"; 
    string file; 
    cin >> file; 
    ifstream is(file.c_str()); 
    if (!is) cerr << "File doesn't exist.\n"; 

    multimap<Customer, Purchase, Cmp_name> orders; 

    while (!is.eof()) { 
     Customer c; 
     Purchase p; 

     is >> c; 
     is >> p; 

     orders.insert(make_pair(c,p)); 
    } 

    for (multimap<Customer, Purchase, Cmp_name>::iterator it = orders.begin(); it!=orders.end(); ++it) 
     cout << it->first << it->second << "\n\n"; 

} 

回答

2

至於你的客戶/採購ostream的插入器,宣告第二個參數常量&代替非const &。例如:

ostream& operator<<(ostream& out, Customer const& c) 

這是必要的,因爲在一個地圖的關鍵是,即使你使用非const迭代器(修改鍵將無效任何樹排序或哈希地圖實現使用一成不變的

最好檢查每個istream提取操作是否成功,並在第一次不成功時跳出循環。「is.eof()」不會讀取任何額外的(如空格)字符,所以它可能在文件的語義末尾聲明「!eof()」。

類似於:

for(;;) { 
     Customer c; 
     Purchase p; 

     if (!getline(is, c.name)) break; 
     if (!getline(is, c.address) break; 
     if (!getline(is, p.product_name) break; 
     if (!(is >> p.unit_price >> p.count)) break; 

     orders.insert(make_pair(c,p)); 
} 

由於這些都返回原始的istream,所以在每次嘗試輸入之後都有一個「if(!is)break;」。

您還可以通過爲客戶和購買定義提取器來簡化某些操作,例如,

istream的&操作>>(istream的&我,客戶& C)

故障讀取客戶先給你打出來(如果EOF得手停止閱讀的IStream將評估爲假)。

顯然你可以使一些失敗的輸入點「ok to eof」,並在所有其他情況下給出一個特定的錯誤。

+0

我實際上通常把它當作const類型&var,但是謝謝 - 愚蠢的錯誤。我會嘗試你的測試,看看我想出了什麼。 – trikker 2009-09-01 01:51:28

+0

爲了更簡潔的代碼,我重載了istream,但它仍然有一個無限循環。我用一些輸出做了一段時間(真正的)測試,它通過數據循環兩次然後凍結。 – trikker 2009-09-01 02:04:27

+0

那是因爲你沒有「if(!(is >> c))break;」 – 2009-09-01 02:23:20