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

怎么清除EOF?

[复制链接]
楼主
发表于 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 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标准库里没流这个概念
板凳
发表于 2014-3-21 20:40:19 | 显示全部楼层
981013 发表于 2014-3-21 20:31
试了一下,好像和平台有关,linux下没有问题,Windows下要求在cin.get时再按一个回车,Mac OS则根本没用
...

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

你的编译环境?我去试试看
地板
发表于 2014-3-21 20:43:12 | 显示全部楼层
另外你是怎么输入的?
1
2 ctrl+D

还是
1
2
ctrl+D
?

windows下面的EOF的输入和unix下面不一样,这点没搞错吧?
5#
发表于 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
6#
发表于 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
7#
发表于 2014-3-23 14:54:14 | 显示全部楼层
981013 发表于 2014-3-23 14:48
Mac OS (UNIX)下这段代码就死循环了其他系统下都没问题

没明白,那段本来就是死循环啊?
8#
发表于 2014-3-23 15:08:41 | 显示全部楼层
981013 发表于 2014-3-23 15:07
就是不停输出-1

你在OS X下面用的是哪个shell? bash还是其他的? 我去试试看
9#
发表于 2014-3-23 15:52:33 | 显示全部楼层
981013 发表于 2014-3-23 15:20
是bash
不过一般用的是xCode的虚拟终端

确实是个问题,让我研究研究看看
10#
发表于 2014-3-23 16:02:03 | 显示全部楼层
简单的对应方法
  1. #include <stdio.h>

  2. int main()
  3. {
  4.   while(1){
  5.     int ch;
  6.     ch = getchar();
  7.     if(ch != EOF)
  8.       printf(" %d\n", ch);
  9.     else
  10.       clearerr(stdin);
  11.   }
  12.   return 0;
  13. }
复制代码


可能在libc或者系统接口上OS X和Linux的实现有点不同
11#
发表于 2014-9-7 21:58:50 | 显示全部楼层
当时的回复有个地方不怎么确定,这个问题其实可以比照一下OSX和Linux的man page

OSX getchar (3)
The end-of-file condition is remembered, even on a terminal, and all subsequent attempts to
     read will return EOF until the condition is cleared with clearerr(3).

https://developer.apple.com/libr ... man3/getchar.3.html

linux getchar (3)
http://man7.org/linux/man-pages/man3/getchar.3.html

没有强调terminal会记住EOF的状态
12#
发表于 2014-9-8 11:33:07 | 显示全部楼层
981013 发表于 2014-9-8 11:30
也就是说在Mac OS上终端记住了EOF,然后在clearerr之前都不能正常读取?

是的
另外文档下面标着BSD,说明在BSD系统中应该都是这样

另,现在没有Mac OS,只有OS X
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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