【问题标题】:Error triggered when reading structured values读取结构化值时触发错误
【发布时间】:2020-07-21 10:15:56
【问题描述】:

我试图弄清楚为什么“使用 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),设置为失败状态并返回 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");
    }

【问题讨论】:

  • 请提供minimal reproducible example,以便我们运行这段代码,看看是什么问题。
  • 也缺少大括号,因此您的代码无效。所以我怀疑是拼写错误。
  • 我已经对其进行了测试,重现了问题,这是一个错字(缺少大括号)。还有其他一些小问题,基本上修复错字后可以正常工作:godbolt.org/z/f48Y4r
  • @Theodore 创建minimal reproducible example 时,请包含您在问题中使用的代码。不要链接到外部网站。您链接到的头文件包含许多不相关的内容和大量不需要的头文件。
  • @Theodore 我已经更正了我的回复。你必须以某种方式处理文件的结尾,这就是为什么我没有把 return 我不知道你想如何处理它,但是是的,没有 return 它只是转到以下语句。

标签: c++ istream


【解决方案1】:

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

    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

您的文件已完成。一切都正确读取,但文件结束。

你还有额外的回报:

    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++ 中的缩进没有任何意义。

【讨论】:

  • 这是我 40 分钟前评论的内容。
  • @MarekR 在发布回复之前我没有看到您的评论。无论如何,OP 对两种不同的东西(文件结尾或 istream 错误和错误的文件格式)进行了测试,我不认为这是一个错字,因为这两种东西都应该区别对待。
猜你喜欢
  • 2018-03-24
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2016-12-26
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多