文件循环和读入地图的问题

时间:2009-09-01 01:37:11

标签: c++

我从文件读入时的while循环不会中断。我不确定问题是什么。如果您需要更多信息,请询问。

代码:

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

using namespace std;

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

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

// Function Object for comparison in map container
struct Cmp_name {
    bool operator()(const Customer& first, const Customer& second)
    { return first.name < second.name; }
};

// ostream overloads
ostream& operator<<(ostream& out, const Customer& c)
{
    out << c.name << '\n'
        << c.address << '\n';
    return out;
}

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

istream& operator>>(istream& in, Customer& c)
{
    getline(in, c.name);
    getline(in, c.address);
    return in;
}

istream& operator>>(istream& in, Purchase& p)
{
    getline(in, p.product_name);
    in >> p.unit_price >> p.count;
    return in;
}

int main()
{
    cout << "Enter file to read orders from: \n";
    string file;
    cin >> file;
    ifstream is(file.c_str());
    if (!is) cerr << "File doesn't exist.\n";

    multimap<Customer, Purchase, Cmp_name> orders;

    while (!is.eof()) {
        Customer c;
        Purchase p;

        is >> c;
        is >> p;

        orders.insert(make_pair(c,p));
    }

    for (multimap<Customer, Purchase, Cmp_name>::iterator it = orders.begin(); it!=orders.end(); ++it)
        cout << it->first << it->second << "\n\n";

}

1 个答案:

答案 0 :(得分:2)

对于您的Customer / Purchase ostream插入器,声明第二个参数const&amp;而不是非const&amp ;.例如:

ostream& operator<<(ostream& out, Customer const& c)

这是必要的,因为即使你使用非const迭代器,映射中的键也是不可变的(修改键会使地图实现使用的任何树排序或散列无效。

最好检查每个istream提取操作是否成功,并在第一次没有成功时突破循环。你的“is.eof()”不会读取任何额外的(例如空格)字符,因此它可能在文件的语义末尾声称“!eof()”。

类似的东西:

for(;;) {
        Customer c;
        Purchase p;

        if (!getline(is, c.name)) break;
        if (!getline(is, c.address) break;
        if (!getline(is, p.product_name) break;
        if (!(is >> p.unit_price >> p.count)) break;

        orders.insert(make_pair(c,p));
}

由于这些都返回原始的istream,它与“if(!is)break”相同。在每次尝试输入之后。

您还可以通过为Customer和Purchase定义提取器来简化某些事情,例如

istream的&安培;运营商&gt;&gt;(istream&amp; i,客户&amp; c)

无法读取客户会让您爆发(如果eof停止读取成功,则istream将评估为false)。

显然,您可以将一些失败的输入点“放到eof”,并在所有其他情况下给出特定的错误。