搜索
查看: 2934|回复: 22
打印 上一主题 下一主题

怎么清除EOF?

[复制链接]
跳转到指定楼层
楼主
发表于 2014-3-16 16:47:59 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
5啊哈币
如题,请给出C和C++两种方案
(C++):cin.clear()还不够,cin的错误标志被清除了,但仍不能接受输入。

最佳答案

查看完整内容

对于原始的代码,我试验出了两种解决方法,首先是看似没道理的再清一次stdin 然后我想,会不会是实现上有个bug,stdin标记着EOF,后面一同步,然后非EOF状态的std::cin也变成EOF了,然后就试了一下关掉同步…… 居然也能解决……orz 不知道是libc++实现上的问题还是设计上的鸟问题……
沙发
发表于 2014-3-16 16:48:00 | 只看该作者
对于原始的代码,我试验出了两种解决方法,首先是看似没道理的再清一次stdin
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main(int argc, const char * argv[])
  5. {
  6.     vector<int> vec;
  7.     while (cin)
  8.     {
  9.         int ls;
  10.         cin>>ls;
  11.         vec.push_back(ls);
  12.     }
  13.     cin.clear();
  14.     clearerr(stdin);
  15.     if (cin)
  16.     {
  17.         cout<<"Good cin!"<<endl;
  18.     }
  19.     int a;
  20.     cin>>a;
  21.     cout<<a<<endl;
  22.     cout << "Hello, World!\n";
  23.     return 0;
  24. }
复制代码


然后我想,会不会是实现上有个bug,stdin标记着EOF,后面一同步,然后非EOF状态的std::cin也变成EOF了,然后就试了一下关掉同步……

  1. #include <iostream>
  2. #include <vector>
  3. #include <ios>
  4. using namespace std;
  5. int main(int argc, const char * argv[])
  6. {
  7.     ios_base::sync_with_stdio(false);
  8.     vector<int> vec;
  9.     while (cin)
  10.     {
  11.         int ls;
  12.         cin>>ls;
  13.         vec.push_back(ls);
  14.     }
  15.     cin.clear();
  16.     if (cin)
  17.     {
  18.         cout<<"Good cin!"<<endl;
  19.     }
  20.     int a;
  21.     cin>>a;
  22.     cout<<a<<endl;
  23.     cout << "Hello, World!\n";
  24.     return 0;
  25. }
复制代码

居然也能解决……orz
不知道是libc++实现上的问题还是设计上的鸟问题……
板凳
 楼主| 发表于 2014-3-16 16:52:58 | 只看该作者
本帖最后由 981013 于 2014-3-16 16:58 编辑

例如:
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main(int argc, const char * argv[])
  5. {
  6.     vector<int> vec;
  7.     while (cin)
  8.     {
  9.         int ls;
  10.         cin>>ls;
  11.         vec.push_back(ls);
  12.     }
  13.     cin.clear();
  14.     if (cin)
  15.     {
  16.         cout<<"Good cin!"<<endl;
  17.     }
  18.     int a;
  19.     cin>>a;
  20.     cout<<a<<endl;
  21.     cout << "Hello, World!\n";
  22.     return 0;
  23. }
复制代码
输出:
输入流中的EOF应该已经在cin>>ls;时被读取了啊?!

未命名.jpg (44.08 KB, 下载次数: 22)

输出

输出
地板
发表于 2014-3-16 20:42:02 | 只看该作者
本帖最后由 超神级 于 2014-3-16 20:45 编辑

测试看看......................
5#
发表于 2014-3-16 22:46:27 | 只看该作者
本帖最后由 rosynirvana 于 2014-3-16 23:12 编辑

原因是cin的flag被清掉了,但是流里面还有EOF这个字符既然知道是残留字符,那就一般的清理残留字符的手段就行
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main(int argc, const char * argv[])
  5. {
  6.     vector<int> vec;
  7.     while (cin)
  8.     {
  9.         int ls;
  10.         cin>>ls;
  11.         vec.push_back(ls);
  12.     }
  13.     cin.clear();

  14.     if (cin)
  15.     {
  16.         cout<<"Good cin!"<<endl;
  17.     }
  18.     if(cin)
  19.       cin.get();
  20.     int a;
  21.     cin>>a;
  22.     cout<<a<<endl;
  23.     cout << "Hello, World!\n";
  24.     return 0;
  25. }
复制代码


C的方法我不确定指什么,C标准库里没流这个概念
6#
 楼主| 发表于 2014-3-21 20:31:01 | 只看该作者
rosynirvana 发表于 2014-3-16 22:46
原因是cin的flag被清掉了,但是流里面还有EOF这个字符既然知道是残留字符,那就一般的清理残留字符的手段就 ...

试了一下,好像和平台有关,linux下没有问题,Windows下要求在cin.get时再按一个回车,Mac OS则根本没用
是否跟回车处理有关?(\r\n之类)
7#
发表于 2014-3-21 20:40:19 | 只看该作者
981013 发表于 2014-3-21 20:31
试了一下,好像和平台有关,linux下没有问题,Windows下要求在cin.get时再按一个回车,Mac OS则根本没用
...

没关系的
不然一个getchar也清不掉缓冲区残留的回车

你的编译环境?我去试试看
8#
发表于 2014-3-21 20:43:12 | 只看该作者
另外你是怎么输入的?
1
2 ctrl+D

还是
1
2
ctrl+D
?

windows下面的EOF的输入和unix下面不一样,这点没搞错吧?
9#
发表于 2014-3-21 21:28:02 | 只看该作者
本帖最后由 rosynirvana 于 2014-3-21 21:35 编辑

首先,和系统处理回车的方式无关
测试代码
  1. #include <stdio.h>

  2. int main()
  3. {
  4.   while(1){
  5.     int ch;
  6.     ch = getchar();
  7.     printf(" %d\n", ch);
  8.   }
  9.   return 0;
  10. }
复制代码


输入
1
显示
49
10

输入
2
显示
50
10
所以程序认为缓冲区中只有\n

然后输入
2ctrl+z
显示
50
26

输入
ctrl+z
显示
-1

EOF在大多数编译环境中的定义是-1

所以可以看到,只有在新一行输入ctrl+z,才会被认为是EOF信号,而同一行则不会

同样,最初的那份代码,如果正确地在新一行输入ctrl+z是不会有问题的,如果在同一行输入就会造成残留字符

看来windows下是这个问题

unix……嗯让我先把raspberry刷一遍再去测试XD
10#
发表于 2014-3-21 23:02:01 | 只看该作者
本帖最后由 rosynirvana 于 2014-3-21 23:31 编辑

然后是linux下的测试

linux下在同一行输入ctrl+d,会刷新缓冲区
在新一行输入ctrl+d,会输入一个EOF

和上面相同的测试代码
输入
1
输出
49
10
输入
2
输出
50
10
输入
ctrl+d
输出
-1
输入
2ctrl+d
整体效果
2 50
换而言之就是自动补充了一个回车来换行
测试原始的代码,在2后面输入ctrl+d什么都不会发生,interesting
11#
 楼主| 发表于 2014-3-23 14:48:31 | 只看该作者
rosynirvana 发表于 2014-3-21 21:28
首先,和系统处理回车的方式无关
测试代码

Mac OS (UNIX)下这段代码就死循环了其他系统下都没问题
12#
发表于 2014-3-23 14:54:14 | 只看该作者
981013 发表于 2014-3-23 14:48
Mac OS (UNIX)下这段代码就死循环了其他系统下都没问题

没明白,那段本来就是死循环啊?
13#
 楼主| 发表于 2014-3-23 15:07:05 | 只看该作者
rosynirvana 发表于 2014-3-23 14:54
没明白,那段本来就是死循环啊?

就是不停输出-1
14#
发表于 2014-3-23 15:08:41 | 只看该作者
981013 发表于 2014-3-23 15:07
就是不停输出-1

你在OS X下面用的是哪个shell? bash还是其他的? 我去试试看
15#
 楼主| 发表于 2014-3-23 15:20:09 | 只看该作者
rosynirvana 发表于 2014-3-23 15:08
你在OS X下面用的是哪个shell? bash还是其他的? 我去试试看

是bash
不过一般用的是xCode的虚拟终端
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

广播台
特别关注
快速回复 返回顶部 返回列表