我在将文件中的数据读入Orders向量时遇到了一些麻烦。
代码:
#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)当问题得到解决时。我将需要处理o.item的输出(当前无法输出的订单中的Purchase的向量,因为没有指定元素)。显然我需要指定要输出的元素,我考虑使用静态int并递增它,但是这需要为每个单独的Order重置,这导致问题3 ...
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 :(得分:0)
我没有详细查看你的代码,但我会给出一句忠告:
“不要混合格式化和未格式化的输入。事实上,根本不要使用来自文件或用户输入的格式化输入。”
好的,这是两句话。答案 1 :(得分:0)
关于问题#3,您可以使用多图而不是矢量。
首先,假设您按如下方式拆分Order类:
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>
即可。添加客户/购买对完全符合您的要求:如果客户尚不存在,则添加他,否则只是将购买添加到现有客户。
当然,要实现这一点,您还需要定义一个比较器。最简单的方法可能是为operator <
类定义Customer
。通过比较名称和忽略地址来实现它。
关于您的其他问题,请避免混合使用getline
和stream_iterator
。它本身并不是错误的,但它变得非常棘手,因为getline一次读取一行,并且流迭代器只是读取到下一个空格。
老实说,C ++ IOStreams库的使用非常糟糕。由于您的数据格式已经完全按行分隔,我可能只是放弃了流迭代器并在任何地方使用getline
。
答案 2 :(得分: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;
}
原因是当使用>>
时,它会在newline
中留下getline
字符。你可以搜索Stackoverflow关于流的一般情况,对这个问题有很多很好的解释。
此外,item
中没有任何名为Order
的内容。您所拥有的是vector
Purchase
:
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;
}