读取结构化值时触发错误

Error triggered when reading structured values

我想弄清楚为什么“使用 C++ 编程原理和实践”中的这段代码会触发错误(“错误阅读”):

#include "D:\std_lib_facilities.h"
/*
 get it from: https://github.com/ltr01/Programming- 
 _Principles_and_Practice_Using_Cpp/blob/master/std_lib_facilities.h
*/
struct Reading
{
    int day;
    int hour;
    double temperature;
};
istream &operator>>(istream &is, Reading &r)
// format: ( 3 4 9.7 )
{
    char ch1;
    if (is >> ch1 && ch1 != '(') // first try the format (day, hour, temperature)
    {                            // could it be a Reading?
        is.unget();              // puts the character back so we can read it in some other way
        is.clear(ios_base::failbit); // puts the istream in fail() state
        return is;                   // return allows us to try to read in some other way
    }
    char ch2;
    int d;
    int h;
    double t;
    is  >> d >> h >> t >> ch2;
    if (!is || ch2 != ')')    // the istream it's not good
        error("bad reading"); // messed-up reading = we bail out because the format is wrong
    return is;
    r.day = d;    
    r.hour = h; 
    r.temperature = t;
    return is; // 
}
void fill_from_file(vector<Reading> &v, const string &name) 
{
    ifstream ist{name}; // open file for reading
    if (!ist)
        error("can't open input file ", name); // 
    // . . . use ist . . .
    for (Reading r; ist >> r;) 
        v.push_back(r);
}

int main()
try
{
    vector<Reading> day1; // a day is a vector of readings
    fill_from_file(day1, "10.5_reading_in.txt");
    for (Reading r : day1)
        cout << r.day << ' ' << r.hour << ' ' << r.temperature << '\n';
}

catch (exception &e) 
{
    cerr << "Error: " << e.what() << endl;
    return 1;
}
catch (...)
{
    cerr << "Unknown exception!\n";
    return 2;
}

当我尝试读取此文件时:

(1 1 1.1)
(2 2 2.2)
(3 3 3.3)
(4 4 4.4)
(5 5 5.5)
(6 6 6.6)
(7 7 7.7)
(8 8 8.8)
(9 9 9.9)

我对发生的事情的理解是这样的:

  1. 我们读取第一个字符,如果它不是“(”,它会将字符放回 istream(使用 unget),将状态设置为失败,returns istream尝试以其他方式阅读它

  2. 现在它试图在没有括号的情况下读取它(这是书中的代码)但是因为第一个字符确实是“(”我得到了“错误阅读”错误

  3. 我试图通过读取 ch1 来更改代码,如下所示,但错误(“错误读取”)再次触发:

    是 >> ch1 >> d >> h >> t >> ch2;

我做错了什么?非常感谢您的回答!

更新:感谢 Manuel 的回复,但我无法使其与您的修改一起工作。相反,如果我在到达“文件末尾”时退出该功能,它似乎会起作用。如果我不把 "return is" 放在那里,那么条件 (ch2 != ')') 总是为真,我得到错误 "bad reading" :

// test for end of file or istream error
if (!is) // meaning when is=0 - when it reaches the end
    {
        if (is.eof())
            cout << "Finished" << '\n';
            return is;
        if (is.fail())
            error("wrong character type"); 
    }
    // test for wrong file format
if (ch2 != ')')
    {
        cout << "Readed: " << ch2 << '\n';
        error("bad reading");
    }

如果你设置两个条件来检查输入流和字符读取,你将看到错误:

    if (!is) {
        cout << "Finished" << endl;
        return is;
    }
    
    if (ch2 != ')') {   // the istream it's not good
        cout << "Readed: " << ch2 << endl;
        error("bad reading"); // messed-up reading = we bail out because the format is wrong
    }

输出:

Finished
Readed: 
bad reading

您的文件已完成。全部读取正确,但文件结束。

你还有一个额外的 return:

    if (!is || ch2 != ')')
        error("bad reading");

    return is;  // <-- I suppose this was for debugging, remove it
    r.day = d;    
    r.hour = h; 
    r.temperature = t;
    return is; //

经过这些更改,我的输出是:

Finished
Readed: 
bad reading
1 1 1.1
2 2 2.2
3 3 3.3
4 4 4.4
5 5 5.5
6 6 6.6
7 7 7.7
8 8 8.8
9 9 9.9

在您上次编辑的代码中:

if (is.eof())
     cout << "Finished" << '\n';
     return is;

应该有花括号:

if (is.eof()) {
     cout << "Finished" << '\n';
     return is;
}

C++ 中的缩进没有任何意义。