我是一名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
我能做些什么来改善它?
答案 0 :(得分: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();
}
但是,这不是最好的方法。您最好使用map
来避免嵌套循环。 map
类似于数组,但您可以选择使用string
作为索引:
#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
答案 1 :(得分:0)
你有两个while循环,第一个是好的,但第二个while循环将在执行第一个priceofItem查找后终止。它将遍历整个文件以结束第一次查找。当下一次迭代尝试从外部while循环执行时,内部循环为FALSE,其类似于while(false)。 你需要的是一个存储,一个Arraylist,它将存储项目的名称和价格。这将提供从I = 0到I = n的多次迭代。
答案 2 :(得分: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";
}
我也更喜欢保持一些关注点的分离 - 一个函数通常应该只有一个...函数。例如,我更喜欢只读取的读取代码和只写入的代码,而不是单个函数获取一些现有数据,从文件中读取更多数据,然后写出现有数据的组合新数据。
这并不是说后者是可怕的或可怕的或类似的东西 - 只是因为我更喜欢来限制每个功能在合理的时候做一件事。