【发布时间】: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)
我对发生的事情的理解是这样的:
-
我们读取第一个字符,如果不是“(”,则将字符放回 istream(使用 unget),设置为失败状态并返回 istream 以尝试以其他方式读取它
-
现在它尝试在不带括号的情况下阅读它(这是书中的代码),但是因为第一个字符确实是“(”,所以我得到了“错误阅读”错误
-
我尝试通过读取 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 它只是转到以下语句。