getchar()未按回车时无法读取单个EOF的问题排查
问题描述
需要读取如下格式的文本:
text textEOF
其中EOF为单个Ctrl+D,其余为普通字符(\n必须保留)。但当前代码仅在输入两个EOF时才会停止(格式如下),无法满足需求:
text textEOFEOF
使用getchar()实现的代码如下,请问哪里有问题?
string a; int current; do { current = getchar(); if(current != EOF) a.push_back((char)current); } while ( current != EOF ); cout << a;
原因分析
这是类Unix系统终端的行缓冲输入机制导致的:
- 默认情况下,终端输入是行缓冲模式,输入的内容会先存在缓冲区,直到按下回车或缓冲区满才会发送给程序;
- 当你输入完内容后按一次
Ctrl+D,如果缓冲区不为空,这次操作只会把缓冲区里的所有内容立即发送给程序,并不会触发EOF; - 只有当缓冲区为空时,按下
Ctrl+D才会让getchar()返回EOF,程序才会停止循环。
所以你输入text\ntext后按第一次Ctrl+D,程序只是把缓冲区里的text\ntext全部读取,此时getchar()会继续等待输入,直到你再按一次Ctrl+D(此时缓冲区为空)才会返回EOF。
解决方法
有两种可行的方案:
方案1:修改终端缓冲模式
在程序开头添加代码,将标准输入设置为无缓冲模式,这样输入的每个字符都会立即发送给程序,按下一次Ctrl+D就会触发EOF:
#include <iostream> #include <cstdio> #include <string> using namespace std; int main() { // 设置标准输入为无缓冲 setvbuf(stdin, NULL, _IONBF, 0); string a; int current; do { current = getchar(); if(current != EOF) a.push_back((char)current); } while ( current != EOF ); cout << a; return 0; }
方案2:调整输入方式(无需修改代码)
输入完最后一行内容后,先按回车(将缓冲区内容发送给程序),然后立即按Ctrl+D(此时缓冲区为空,触发EOF)。但这种方式会在文本末尾多一个\n,如果你的需求不允许额外的换行,这个方案不适用。
内容的提问来源于stack exchange,提问作者Purple6
相关产品推荐
相关产品推荐

