1

我是一个 C++ 菜鸟,不知道我做错了什么。我的任务是比较两个不同的 .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

这是因为在第一次之后

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

然而,这不是最好的方法。你最好使用 amap来避免嵌套循环。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

您有两个 while 循环,第一个是可以的,但是第二个 while 循环将在执行第一个 priceofItem 查找后终止。它将遍历整个文件以结束第一次查找,并且当下一次迭代尝试从外部while循环执行时,内部循环为FALSE,类似于while(false)。你需要的是一个存储,一个数组列表,它将存储项目的名称和价格。这将提供从 I = 0 到 I = n 的多次迭代。

于 2013-07-24T00:29:23.050 回答
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";
}

我也更喜欢保持一些关注点分离——一个函数通常应该有一个...函数。例如,我更喜欢读取只读取的代码和只写入写入的代码,而不是使用单个函数获取一些现有数据,从文件中读取更多数据,然后写出现有数据的组合与新数据。

这并不是说后者是可怕的或可怕的或类似的东西——只是我更愿意在合理的情况下限制每个功能做一件事。

于 2013-07-24T06:22:55.740 回答