c ++读取txt文件并复制到两个类istream :: peek()

时间:2017-01-05 01:35:14

标签: c++ fstream istream peek

istream& operator>>(istream& s, vector<Order>& ord) {

    string c{};
    bool got_customer = false;
    Customer temp_customer{};
    vector<Purchase>vec_purchase{};
    while (s >> c) {
        cout << "Erstes Wort der Zeile: "<<c << endl;

        if (!got_customer) { //c[0] == '#'
            c.erase(c.begin()); //löscht erstes Element vom string
            int k_nummer{};
            string k_vname{};
            string k_nname{};
            string k_plz{};
            string k_stadt{};
            k_nummer = stoi(c); //string to int
            s >> k_vname >> k_nname >> k_plz>>k_stadt;
            k_vname += " " + k_nname;
            temp_customer = Customer(k_nummer, k_vname, k_plz, k_stadt);
            got_customer = true;
        } else {
            string p_name{};
            double p_preis{};
            int p_menge{};
            p_name = c;
            s >> p_preis>>p_menge;
            cout << p_name << "  " << p_preis << "  " << p_menge << endl;
            vec_purchase.push_back(Purchase{p_name, p_preis, p_menge});
        }

        cout<<s.peek()<<endl;
        if (s.peek() == '#') {
            ord.push_back(Order{temp_customer, vec_purchase});
            temp_customer = Customer{};
            vec_purchase.clear();
            got_customer = false;
        }
    }
}

这是txt文件:

#725454 Schenker Rudolf DE-30159 Hannover
Shirt 135.95 1
Tie 89.59 1
#987654 Orbison Roy US-TN37075 Hendersonville
Mug 1.49 3
T-Shirt 14.90 1
#123456 Petty Tom US-FL32641 Gainesville
Flashlight 12.95 2
#246802 Hite Bob US-CA90291 Venice
CannedBeans 0.89 10
CannedTomatoes 1.79 6
#246802 Hite Bob US-CA90291 Venice
CanOpener 0.48 1
Spoon 1.49 4
Needle 0.05 100

以'#'开头的行是Customer对象。 其他行是购买对象。

我正在试图查看即将到来的char,但我一次又一次地获得相同的字符。在这种情况下,我总是得到'13'作为s.peek()的输出。

€二叔: 谢谢@Mark Ransom。 如果有人遇到同样的问题,这是工作代码。 :)

istream& operator>>(istream& s, vector<Order>& ord) {
    string c{};
    bool got_customer = false;
    Customer temp_customer{};
    vector<Purchase>vec_purchase{};

    while (s >> c) {
        if (!got_customer) { 
            c.erase(c.begin()); //deletes first char of string
            int k_nummer{};
            string k_vname{};
            string k_nname{};
            string k_plz{};
            string k_stadt{};
            k_nummer = stoi(c); //string to int
            s >> k_vname >> k_nname >> k_plz>>k_stadt>>ws;
            k_vname += " " + k_nname;
            temp_customer = Customer(k_nummer, k_vname, k_plz, k_stadt);
            got_customer = true;
        } else {
            string p_name{};
            double p_preis{};
            int p_menge{};
            p_name = c;
            s >> p_preis>>p_menge>>ws;
            vec_purchase.push_back(Purchase{p_name, p_preis, p_menge});
        }

        if (s.peek() == 35||s.peek() == -1 ) {  //35 (in ascii) -> # , -1 -> end of txt file
            ord.push_back(Order{temp_customer, vec_purchase});
            temp_customer = Customer{};
            vec_purchase.clear();
            got_customer = false;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

当您从流中读取时,输入将停止在第一个空白字符上。十进制代码为13的字符是ASCII CR,它出现在Windows的每一行的末尾;它被认为是空白。您需要跳过空格才能找到下一个重要字符。您可以使用std::ws执行此操作。

s >> k_vname >> k_nname >> k_plz >> k_stadt >> std::ws;

s >> p_preis >> p_menge >> std::ws;

答案 1 :(得分:0)

 s >> p_preis>>p_menge;

这是为了读取带有记录的行上的最后两个字段。紧接着:

 if (s.peek() == '#') {

你明显的目的是窥探下一行的第一个字符,检查下一行是否以#开头。

嗯,这不会发生,就像那样......

问题是>>运算符在处理完输入后不会消耗行尾字符。 peek()这里将为您提供换行符。惊喜。

给出一个示例输入行:

 Tie 89.59 1

&#34; 1&#34;部分将由>>p_menge阅读,并存储到menge1之后的下一个字符将是换行符,而peek()将很乐意为您提供这些字符。

这是完成此任务的错误方法。只有一种正确的方法来读取包含文本行的文件:

std::getline()

那就是它。 std::getline(),没有别的。了解如何使用它。我会让你的生活更加简单。

您当然可以使用>>运算符一次读取输入文件中的行,零碎,一个字段,但正如您所发现的那样,这是一个容易出错且容易出错的过程。太多雷区和陷阱。

当然,使用>>运算符可以做到这一点,但是如何做到这一点并不总是显而易见的,需要完全理解所有细微差别格式化的输入操作。

遗憾的是,有太多介绍性的C ++书籍开始时会出现使用>>运算符读取由文本行组成的输入的示例。这只会使大多数初学者感到困惑,并导致问题和误解,例如这些。

您需要重写程序以使用std::getline()一次读取一行文本。故事结束。

一旦你将整行文字读成std::string,并检查它是否以#字符开头:如果你觉得它 然后 您可以将整行填入std::istringstream,然后在受控环境中使用>>运算符。