简体   繁体   English

文件循环和读入映射问题

[英]Problem with file loop and reading into map

The while loop I have while reading in from a file doesn't break. 从文件读取时的while循环不会中断。 I'm not sure what the problem is. 我不确定是什么问题。 If you need any more information just ask. 如果您需要更多信息,请询问。

Code: 码:

#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";

}

As for your Customer/Purchase ostream inserters, declare the second argument const& instead of non-const &. 对于您的客户/购买ostream插入器,声明第二个参数const&而不是非const&。 For example: 例如:

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

That's necessary because the key in a map is immutable even if you're using a non-const iterator (modifying the key would invalidate whatever tree-sorting or hashing the map implementation uses. 这是必须的,因为即使您使用的是非常量迭代器,映射中的键也是不可变的(修改键将使映射实现使用的任何树排序或散列操作均无效。

It's best to check every istream extraction operation for success, and break out of the loop the first time one doesn't succeed. 最好检查每个istream提取操作是否成功,并在第一次失败时退出循环。 Your "is.eof()" isn't going to read any extra (eg whitespace) characters, so it may claim "!eof()" at the semantic end of file. 您的“ is.eof()”将不会读取任何额外的字符(例如,空格),因此它可能会在文件的语义结尾声明“!eof()”。

Something like: 就像是:

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

Since those all return the original istream, it's the same as having a "if (!is) break;" 由于所有这些都返回原始istream,因此与“ if(!is)中断;”相同。 after every attempted input. 在每次尝试输入之后。

You can also simplify things somewhat by defining extractors for Customer and Purchase, eg 您还可以通过定义“客户”和“购买”的提取器来简化一些事情,例如

istream& operator>>(istream &i,Customer &c) istream&运营商>>(istream&i,Customer&c)

A failure to read a Customer would let you break out (the istream will evaluate as false if an eof stops the read from succeeding). 未能读取Customer会让您分手(如果eof阻止读取成功,则istream会评估为false)。

Obviously you can make some of the failed-input points "ok to eof" and give a specific error in all the other cases. 显然,您可以使某些失败的输入点“确定为正确”,并在所有其他情况下给出特定的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM