大家来看看,是C++ primer错了吗?[已解决]

C、C++和Java语言
回复
头像
Nile
帖子: 990
注册时间: 2006-07-15 11:20
来自: 枫叶刀市
送出感谢: 2 次
接收感谢: 0

大家来看看,是C++ primer错了吗?[已解决]

#1

帖子 Nile » 2008-10-24 11:44

C++ primer 4th上有这样的示例: P289

代码: 全选

#include	<iostream>
#include	<exception>
#include	<stdexcept>
#include	<fstream>

using namespace std;

int main(){
	int st;
	while(cin>>st,!cin.eof()){
		if(cin.bad())
			throw runtime_error("error");
		if(cin.fail()){
			cerr<<"bad data, try again";
			cin.clear(istream::failbit);
			continue;
		}
	}
}
从标准输入流输入整数,如果输入非法字符,就会输出bad data, try again,再用cin.clear把错误状态清除,重新输入。
可运行结果是一旦输入非法字符,就进入死循环...

Google后发现是因为字符缓冲没有清除,导致每次循环都自动输入上次的非法字符,必须用cin.ignore()清空缓存

但是我发现如果只在cin.clear(istream::failbit);后加cin.ignore()依然会进入死循环,必须改成如下:

代码: 全选

#include	<iostream>
#include	<exception>
#include	<stdexcept>
#include	<fstream>
using namespace std;

int main(){
	int st;
	while(cin>>st,!cin.eof()){
		if(cin.bad())
			throw runtime_error("error");
		if(cin.fail()){
			cerr<<"bad data, try again";
			cin.clear();                    //change here++++++++++
			cin.ignore();                  //change here++++++++
			continue;
		}
	}
}
就可以正确执行了

请问各位是C++primer写错了吗?为什么cin.clear()指定单一标识cin.clear(istream::failbit)后不起作用?

还有一个问题while(cin>>st,!cin.eof())在标准输入流中好像并不起作用,但在标准文件流中却可以用,是不是说系统不把输入缓冲区的底部当作文件结尾EOF判断?

谢谢各位哈!
上次由 Nile 在 2008-10-25 8:40,总共编辑 1 次。
Thinkpad T400
头像
自由建客
论坛版主
帖子: 13436
注册时间: 2008-07-30 23:21
系统: Debian stable AMD64
来自: freebuilder@yeah.net
送出感谢: 12 次
接收感谢: 112 次
联系:

Re: 大家来看看,是C++ primer错了吗?

#2

帖子 自由建客 » 2008-10-24 12:25

不会 C++,库写得太复杂了。
看样子, while(cin>>st,!cin.eof()) 本来就是死循环呀。EOF 要用 Ctrl + D 输入。
头像
Nile
帖子: 990
注册时间: 2006-07-15 11:20
来自: 枫叶刀市
送出感谢: 2 次
接收感谢: 0

Re: 大家来看看,是C++ primer错了吗?

#3

帖子 Nile » 2008-10-24 12:34

回楼上
估计是我没说清

按道理说即使循环也应该是每执行一次都让输入数据的,而我说的死循环是不停的输出“bad data, try again”,不再接受数据了
Thinkpad T400
头像
yangcheng
帖子: 498
注册时间: 2005-09-27 18:24
来自: 杭州
送出感谢: 0
接收感谢: 0
联系:

Re: 大家来看看,是C++ primer错了吗?

#4

帖子 yangcheng » 2008-10-24 13:14

赞认真,, 报告错误吧.
头像
Nile
帖子: 990
注册时间: 2006-07-15 11:20
来自: 枫叶刀市
送出感谢: 2 次
接收感谢: 0

Re: 大家来看看,是C++ primer错了吗?

#5

帖子 Nile » 2008-10-25 8:36

又有新进展了
早上查MSDN,M$对basic_io.clear的解释:
void clear(
iostate _State=goodbit
);
Parameters

_State (optional)

The flags you want to set after clearing all flags.
C++ primer原文的解释:
s.clear(flag): Set specified condition state(s) in s to valid. Type of flag is strm::iostate.
仔细看看,解释是不错的,只是后面示例错了。

这是MSDN给的示例,用另一种方法清空缓存:

代码: 全选

#include <iostream>
using namespace std;

int main()
{
   int x;
   cout << "enter choice:";
   cin >> x;
   while (x < 1 || x > 4)
   {
      cout << "Invalid choice, try again:";
      cin >> x;
      // not a numeric character, probably
      // clear the failure and pull off the non-numeric character
      if (cin.fail())
      {
         cin.clear();
         char c;
         cin >> c;
      }
   }
}
看来缓存清理也是必须的。
唉,c++ primer 作者这么牛的专家犯这种错误小不应该啊 :em06
Thinkpad T400
回复

回到 “C/C++/Java”