有关istream的问题

yiskylee 2009-08-03 05:06:47
看C++ primer中的IO部分,有这样一道习题。

编写一个函数,其唯一的形参和返回值都是istream&类型。该函数应一直读取流知道到达文件结束符为止,还应将读到的内容输出到标准输出中。最后,重设流使之有效,并返回该流。并通过cin为实参实现调用来测试上题编写的函数。

答案给的源代码如下:

#include<iostream>
using namespace std;

istream& r_w(istream& s)
{
int ival;
while(s >> ival && !s.eof())
{
if(s.fail())
{
cerr<< "bad data, try again";
s.clear(istream::failbit);
continue;
}

if(s.bad())
throw runtime_error("IO stream corrupted");
cout<<ival<<" ";

}
s.clear();
return s;
}

int main()
{
double dval;
r_w(cin);
cin >> dval;
cout << dval;

return 0;
}

意思就是读入int的值,如果正常就继续读,如果不是int类型的,则会发现s.fail()为真,这时clear一下错误位,然后continue,继续读下一个字符。
而我这个程序跑起来以后,如果遇上形如
"1s2"
这样的字符输入,就会发现当函数遇到s的时候,直接跳出while,不再分析下面的了。意思应该是s>>ival这个为假。

请问一下,是这个答案给错了,还是我的理解有什么问题?谢谢!

...全文
112 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
yiskylee 2009-08-04
  • 打赏
  • 举报
回复
谢谢!
lwlchristy 2009-08-03
  • 打赏
  • 举报
回复
你的理解是正确的,你输入s时编译器会认为输入有误。即:s>>ival这个条件为假。
baihacker 2009-08-03
  • 打赏
  • 举报
回复
看上去你的理解没有问题
13.4.3 Stream State and Boolean Conditions
Two functions are defined for the use of streams in Boolean expressions (Table 13.5).

Table 13.5. Stream Operators for Boolean Expressions Member Function Meaning
operator void*() Returns whether the stream has not run into an error (corresponds to !fail())
operator !() Returns whether the stream has run into an error (corresponds to fail())


With operator void*(), streams can be tested in control structures in a short and idiomatic way for their current state:


// while the standard input stream is OK
while (std::cin) {
...
}


For the Boolean condition in a control structure, the type does not need a direct conversion to bool. Instead, a unique conversion to an integral type (such as int or char) or to a pointer type is sufficient. The conversion to void* is often used to read objects and test for success in the same expression:


if (std::cin >> x) {
// reading x wax successful
...
}


As discussed earlier, the expression


std::cin >> x


returns cin. So after x is read, the statement is


if (std::cin) {
...
}


Because cin is being used in the context of a condition, its operator void* is called, which returns whether the stream has run into an error.

A typical application of this technique is a loop that reads and processes objects:


// as long as obj can be read
while (std::cin >> obj) {
// process obj (in this case, simply output it)
std::cout << obj << std::endl;
}


This is C's classic filter framework for C++ objects. The loop is terminated if the failbit or badbit is set. This happens when an error occurred or at end-of-file (the attempt to read at end-of-file results in setting eofbit and failbit; see page 598). By default, operator >> skips leading whitespaces. This is normally exactly what is desired. However, if obj is of type char, whitespace is normally considered to be significant. In this case you can use the put() and get() member functions of streams (see page 611) or, even better, an istreambuf_iterator (see page 667) to implement an I/O filter.

With operator !, the inverse test can be performed. The operator is defined to return whether a stream has run into an error; that is, it returns true if failbit or badbit is set. It can be used like this:


if (! std::cin) {
// the stream cin is not OK
...
}


Like the implicit conversion to a Boolean value, this operator is often used to test for success in the same expression in which an object was read:


if (! (std::cin >> x)) {
// the read failed
...
}


Here, the expression


std::cin >> x


returns cin, to which operator ! is applied. The expression after ! must be placed within parentheses. This is due to the operator precedence rules: without the parentheses, operator ! would be evaluated first. In other words, the expression


! std::cin >> x


is equivalent to the expression


(!std::cin) >> x


This is probably not what is intended.

Although these operators are very convenient in Boolean expressions, one oddity has to be noted: Double "negation" does not yield the original object:

cin is a stream object of class istream.

!! cin is a Boolean value describing the state of cin.

As with other features of C++, it can be argued whether the use of the conversions to a Boolean value is good style. The use of member functions such as fail() normally yields a more readable program:


std::cin >> x;
if (std::cin.fail()) {
...
}

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧