2009-09-01 8 views
-1

ファイルから読み込み中にwhileループが途切れない。私は問題が何であるか分かりません。それ以上の情報が必要な場合は、尋ねてください。ファイルループの問題とマップへの読み込み

コード:あなたの顧客/購入のostreamのインサータ用として

#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

、代わりに非const &の第2引数のconstの&を宣言します。たとえば、次のように

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

マップ内のキーは、キーを変更する非constイテレータが(マップの実装が使用するどんな木ソートまたはハッシング無効になり使用している場合であっても不変であるため、

必要があります。

あなたの "is.eof()"は余分な(空白などの)文字を読み取るつもりはないので、成功するためにはすべてのistream抽出操作をチェックし、したがって、ファイルの意味論的終わりに "!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の& I、お客様& C)

あなたは(EOFが続くからの読み出しを停止した場合にはistreamは偽と評価されます)抜け出す聞かせお客様を読み取りに失敗しました。

明らかに、失敗した入力ポイントのいくつかを「ok to eof」にして、他のすべてのケースで特定のエラーを出すことができます。

+0

私は実際にはconst型&varとしてそれを持っていますが、おかげで間違いがあります。私はあなたのテストを試し、私が何を思いつくのか見てみましょう。 – trikker

+0

私はクリーナーコードのためにistreamをオーバーロードしましたが、それでも無限ループがあります。私はある出力でしばらく(真の)テストを行い、データを2回ループしてから凍結しました。 – trikker

+0

これは、あなたが "if(!(is >> c))break"を持っていなかったからです。 –