2009-08-30 8 views
1

ファイルのデータをオーダーのベクトルに読み込むときに問題が発生します。ファイルの終わりまでをistream_iteratorとistreamのオーバーロードで読み取る

コード:

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

using namespace std; 

class Purchase; 

class Order { 
public: 
    string name; 
    string address; 
    vector<Purchase> items; 
}; 

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) {} 
}; 

istream& operator>>(istream& in, Order& o) 
{ 
    string p_name; 
    double u_price; 
    int p_count; 

    getline(in, o.name); 
    getline(in, o.address); 
    getline(in, p_name); 
    in >> u_price >> p_count; 

    o.items.push_back(Purchase(p_name, u_price, p_count)); 

    return in; 
} 

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

ostream& operator<<(ostream& out, const Order& o) 
{ 
     out << '\n' << o.name << '\n' 
      << o.address << '\n' 
      << o.item << '\n'; 
     return out; 
} 

int main() 
{ 
    cout << "Enter file to read orders from: \n"; 
    string file; 
    cin >> file; 
    ifstream is(file.c_str()); 

    istream_iterator<Order> ii(is); 
    istream_iterator<Order> eos; 
    ostream_iterator<Order> oo(cout); 
    vector<Order> orders(ii, eos); 

    copy(orders.begin(), orders.end(), oo); 
} 

私は主に3つの質問があります。

1)出力をテストするためにostreamのオーバーロードでo.itemのバグを取り除くと、ファイルの最初のエントリのみが出力されます。 txtファイルは、ベクトル命令に読み込まれることになっている5行のデータのグループで構成されています。

今のところ、txtファイルには10個の「オーダー」がありますが、最初のものはオーダーベクトルにのみ読み込まれます。おそらく何らかのファイル操作の終わりを実装する必要がありますが、istreamのオーバーロードとイテレータを使ってこれを行う方法がわかりません。これが最大の問題です。これを理解できれば、次の2つの質問で大丈夫だろうと思います。

2)この問題が修正されたとき。 o.item(要素が指定されていないため、現在出力できないオーダーのPurchasesのベクトル)の出力に対処する必要があります。明らかに私は出力する要素を指定する必要があります。静的intを使用してインクリメントすることを検討しましたが、これは3つの質問につながるすべての独立したOrderに対してリセットする必要があります...

3)以前の読書と同じ名前/住所が読み込まれるので、読んでいるのと同じ「注文」であることを理解し、新しい注文を作成するのではなくその注文の購入ベクトルに別のオブジェクトを単に追加するというプログラムが必要です。私はfind()を使ってその名前がす​​でに存在するかどうかをチェックし、その場合は名前/アドレスの入力を何もしないことを考えていますが、もっと良い方法があるかどうかを知りたいと思っています。

ご迷惑をおかけします。もっと説明が必要な場合は、詳しく説明します。どんな助けもありがとうございます。ありがとう。

P.S. o.itemの出力をo.item [0]に指定した場合の入力出力の例を次に示します。

テキストファイルがあります。

John Smith 
117 One Tree Hill 
Trampoline 
600.00 
1 

//... 9 more Orders like this 

出力は次のとおりです。

John Smith 
117 One Tree Hill 
Trampoline 
600.00 
1 
//... Nothing after this.... 

答えて

0

質問3については、ベクトルの代わりにマルチマップを使用できます。

まず、次のようにあなたの注文のクラスを分割前提としています

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

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) {} 
}; 

class Order { 
    Customer c; 
    std::vector<Purchase> p; 
}; 

今、あなたは、単にstd::multimap<Customer, Purchase>を作成することができます。顧客/購入ペアを追加することは、あなたが望むものを正確に行います。顧客がまだ存在しない場合は追加されます。そうでない場合は、既存の顧客に購入が追加されます。

もちろん、これが機能するためには、比較機能も定義する必要があります。最も簡単な方法は、Customerクラスに対してoperator <を定義することです。名前を比較し、アドレスを無視して実装します。

その他のご質問は、getlinestream_iteratorを混ぜて使用しないでください。 は間違っていますそのものではありませんが、getlineは一度に1行ずつ読み込み、ストリームイテレータは次の空白に読み込むだけなので、面倒です。

正直なところ、C++ IOStreamsライブラリは一般的に使用するにはかなりひどいです。あなたのデータフォーマットは既にすでに完全に行区切りされているので、おそらくストリームイテレータを削除してどこでもgetlineを使用するだけです。

+0

残念ながら、あなたの解決策は明らかな選択肢になりますが、エクササイズ(私は本のルールに固執しようとしています)ではベクトルを使用するように言います。しかし、これは非常に良い投稿でした。私は2つの答えを設定することができれば。 –

+0

私は実際にベクトルに慣れていて、マルチマップをあまり使わないので、これに切り替えることにしました。私は、コンターのために関数オブジェクトを使うことができます。 –

0

私は詳細にあなたのコードを見ていないが、私はアドバイスの一文与える:「

を書式付き入力と書式なし入力を混在させないでください。実際には、ファイルやユーザー入力からの書式付き入力は使用しないでください。

OK、それは2つの文章でした。

+0

その後、あなたは私がそれを読むことをお勧めだろうか? –

+0

一度に1行ずつ読む。あなたが読んだものを処理するコードを書く。実際のプログラムの最大の部分は、入力を処理します。 –

+0

istream_iteratorとistreamのオーバーロードは基本的にはそうではありませんか?私はそれが全体のファイルを読むことができたらそれが働くことができることを知っている。ところで、これは演習ではなく、プロダクションコードなので、私は大規模な処理について心配していません。 –

0

問題は非常に簡単です。実際には、あなたのコードは非常に明確である:)

あなたがそれらのシンプルなラインです追加しなければならないものをすべて:

istream& operator>>(istream& in, Order& o) 
{ 
    string p_name; 
    double u_price; 
    int p_count; 

    getline(in, o.name); 
    getline(in, o.address); 
    getline(in, p_name); 

    in >> u_price >> p_count; 

    // 
    while(in.peek() == '\n' || in.peek() == ' ') 
    { 
     in.ignore(); 
    } 
    // 

    o.items.push_back(Purchase(p_name, u_price, p_count)); 

    return in; 
} 

理由は>>を使用しているとき、それはgetlineとは異なり、ストリーム内のnewline文字を残していることです。あなたは一般的にストリームについてのStackoverflowを検索することができます問題についての大きな説明がたくさんあります。

itemという名前のものはありません。あなたが持っていることはPurchasevectorです:

ostream& operator<<(ostream& out, const Order& o) 
{ 
     out << '\n' << o.name << '\n' 
      << o.address << '\n'; 
     // 
     for(vector<Purchase>::const_iterator i = o.items.begin(); 
      i != o.items.end(); i++) 
     { 
      out << *i << '\n'; 
     } 
     // 

     return out; 
} 
+0

私はコードを編集していたときにアイテムのことがタイプミスでしたが、これは大変感謝してくれました。 –

関連する問題