当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 5 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 大家来看看,是C++ primer错了吗?[已解决]
帖子发表于 : 2008-10-24 11:44 
头像

注册: 2006-07-15 11:20
帖子: 990
地址: 枫叶刀市
送出感谢: 2
接收感谢: 0 次
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判断?

谢谢各位哈!


_________________
Thinkpad T400


最后由 Nile 编辑于 2008-10-25 8:40,总共编辑了 1 次

页首
 用户资料  
 
2 楼 
 文章标题 : Re: 大家来看看,是C++ primer错了吗?
帖子发表于 : 2008-10-24 12:25 
头像

注册: 2008-07-30 23:21
帖子: 13221
地址: freebuilder@yeah.net
系统: Debian stable AMD64
送出感谢: 36
接收感谢: 121
不会 C++,库写得太复杂了。
看样子, while(cin>>st,!cin.eof()) 本来就是死循环呀。EOF 要用 Ctrl + D 输入。


_________________
(2015-11-16 更新)适合 WM 的截图脚本
(2015-08-24 更新)Debian、Ubuntu 源列表说明
(2013-02-01 首发)文字如何绘出
▷▷ 【更 多 在 此】 ◁◁
箪食瓢饮随遇安,不求栋梁求参天。
【初韵】一门牛逼的编程语言。


页首
 用户资料  
 
3 楼 
 文章标题 : Re: 大家来看看,是C++ primer错了吗?
帖子发表于 : 2008-10-24 12:34 
头像

注册: 2006-07-15 11:20
帖子: 990
地址: 枫叶刀市
送出感谢: 2
接收感谢: 0 次
回楼上
估计是我没说清

按道理说即使循环也应该是每执行一次都让输入数据的,而我说的死循环是不停的输出“bad data, try again”,不再接受数据了


_________________
Thinkpad T400


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 大家来看看,是C++ primer错了吗?
帖子发表于 : 2008-10-24 13:14 
头像

注册: 2005-09-27 18:24
帖子: 498
地址: 杭州
送出感谢: 0 次
接收感谢: 0 次
赞认真,, 报告错误吧.


页首
 用户资料  
 
5 楼 
 文章标题 : Re: 大家来看看,是C++ primer错了吗?
帖子发表于 : 2008-10-25 8:36 
头像

注册: 2006-07-15 11:20
帖子: 990
地址: 枫叶刀市
送出感谢: 2
接收感谢: 0 次
又有新进展了
早上查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


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 5 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译