1

私は C++ 初心者で、何が間違っているのかわかりません。私の課題は、2 つの異なる .txt ファイルを比較することです。それぞれのファイルには、アイテムとそのアイテムの数および価格のいずれかが含まれています。次に、アイテムの名前と価格を印刷しようとしています。以下を含む .txt ファイル namesAndQuantity.txt を使用しているとします。

3 books
4 pens

そして、以下を含む .txt ファイル namesAndPrice.txt:

pens 3.45
books 19.55

私が使用しているコードは、最初の一致のみを出力します:

#include <iostream>
#include <fstream>
#include <cmath>

int main(){
    string nameOfItemP, nameOfItemQ;
    double priceOfItem;
    int numberOfItems;
    ifstream inData;
    ifstream inData2;
    inData.open("namesAndQuantity.txt");
    inData2.open("namesAndPrice.txt");
    while (inData>>numberOfItems>>nameOfItemQ){
        while (inData2>>nameOfItemP>>priceOfItem){
            if (nameOfItemP==nameOfItemQ){
               cout<<nameOfItemQ<<endl;
               cout<<priceOfItem;
        }   
    }
}

このコードは最初の行のみを出力します:

books
19.55

改善するにはどうすればよいですか?

4

3 に答える 3

2

1回目以降だから

while (inData2>>nameOfItemP>>priceOfItem){
    if (nameOfItemP==nameOfItemQ){
        cout<<nameOfItemQ<<endl;
        cout<<priceOfItem;
    }   

実行され、inData2最後に到達し、それ以上読み取られません。open解決策は、関数をwhileループに移動することです。

while (inData>>numberOfItems>>nameOfItemQ){
    inData2.open("namesAndPrice.txt");
    while (inData2>>nameOfItemP>>priceOfItem){
        if (nameOfItemP==nameOfItemQ){
           cout<<nameOfItemQ<<endl;
           cout<<priceOfItem;
    }
    inData2.close();  
}

ただし、これは最善の方法ではありません。mapネストされたループを避けるためにa を使用することをお勧めします。Amapは配列に似ていますが、astringをインデックスとして使用することを選択できます。

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

using namespace std;

int main() {
    // same as before
    int numberOfItems;
    string nameOfItem;
    double price;

    // create a map, using string as index and int as value.
    map<string, int> items;

    ifstream inData("namesAndQuantity.txt");
    ifstream inData2("namesAndPrice.txt");

    while (inData >> numberOfItems >> nameOfItem)
      items[nameOfItem] = numberOfItems;

    while (inData2 >> nameOfItem >> price)
      cout << nameOfItem << " "
           << items[nameOfItem] << " " << price << endl;

    inData.close();
    inData2.close();

    return 0;
}

出力

pens 4 3.45
books 3 19.55
于 2013-07-24T00:03:50.900 に答える
0

@Yang は少なくともいくつかの正しい一般的なアイデアを持っていると思いますが、私は少し違うやり方をすると思います。彼のコードは、データを読み取り、ここで規定されているとおりに表示する場合にのみ有効です。すべてのデータを保存するなど、もう少し汎用的な適用性を持つコードを見たいので、(たとえば)別の形式で印刷したり、印刷する前にフィルターしたりしたい場合は、もう少し実用的です。それを念頭に置いて、次のようなコードをもう少し書きます。

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

struct item {
    int quantity;
    double p;

    friend std::ostream &operator<<(std::ostream &os, item const &j) {
        return os << "\t(" << j.quantity << ")\t$" << j.p;
    }
};

std::ostream &operator<<(std::ostream &os, std::pair<std::string, item> const &r) {
    return os << r.first << ":" << r.second;
}

void read_quantities(std::string const &fname, std::map<std::string, item> &items) {
    std::ifstream in{ fname };
    std::string name;
    int temp;
    while (in >> temp >> name)
        items[name].quantity = temp;
}

void read_prices(std::string const &fname, std::map<std::string, item> &items) {
    std::ifstream in{fname};
    std::string name;
    double temp;
    while (in >> name >> temp)
        items[name].p = temp;
}

int main() {
    std::map<std::string, item> items;

    read_quantities("quantities.txt", items);
    read_prices("prices.txt", items);

    for (auto const & item : items)
        std::cout << item << "\n";
}

また、関心の分離を維持することも好みます。関数は通常、単一の...関数を持つ必要があります。たとえば、既存のデータを取得し、ファイルからさらにデータを読み取り、既存のデータの組み合わせを書き出す単一の関数を使用するよりも、読み取り専用のコードと書き込み専用のコードを好む新しいデータで。

後者がひどい、ひどい、またはそのようなものだと言っているわけではありません-合理的な場合に、各機能を1つのことだけに制限したいというだけです。

于 2013-07-24T06:22:55.740 に答える
0

2 つの while ループがあります。最初のループは問題ありませんが、2 番目の while ループは最初の priceofItem 検索を実行した後に終了します。ファイル全体をトラバースして最初のルックアップを終了します。次の反復が外側の while ループから実行しようとすると、内側のループは while(false) のように FALSE になります。必要なのは、アイテムの名前と価格を格納するストレージ、Arraylist です。これにより、I = 0 から I = n までの複数の反復が提供されます。

于 2013-07-24T00:29:23.050 に答える