如果输入缓冲区不为空,请使用getchar.()检测Ctrl+d

Detect Ctrl+d if input buffer is not empty using getchar()

本文关键字:getchar 检测 Ctrl+d 请使用 缓冲区 输入 如果      更新时间:2023-10-16

我正在编写一个类似shell的解释器,使用getchar()作为缓冲输入。

  • 如果按下Enter,解释器应该处理缓冲区,然后提示输入新行
  • 如果按下Ctrl+d,解释器应处理缓冲区,然后退出

下面的代码可以运行,但不能完全满足第二个要求。

#include <iostream>
using namespace std;
void shell() {
for (int input;;) {
// prompt at beginning of line
std::cout << ">>> "; 
while ((input = getchar()) != 'n') { 
// still in current line
if (input == EOF) {
// ctrl+d pressed at beginning of line
return;
} 
std::cout << "[" << (char)input << "]";
}
// reached end of line
}
}
int main() {
cout << "before shell" << endl;
shell();
cout << "shell has exited" << endl;
return 0;
}

我的问题是getchar()只在缓冲区为空时返回EOF。按Ctrl+d中间行可使getchar()返回除EOF字符本身之外的每个缓冲字符

如何确定Ctrl+d是否在中线按下

我已经考虑过使用超时。在这种方法中,如果getchar()在返回换行以外的内容后停顿太久,解释器会假设Ctrl+d被按下。这不是我最喜欢的方法,因为它需要线程,引入延迟,并且不清楚合适的等待期。

对于法线,末尾有一个'n'。Unix land shell中使用Ctrl+D推送的行不是这样。例如,

#include <stdio.h>
#include <unistd.h>     // read
void shell()
{
char line[256];
for( bool finished = false; not finished; )
{
printf( ">>> " );
//fgets( line, sizeof( line ), stdin );
fflush( stdout );
const int n_bytes = read( 0, line, sizeof( line ) - 1 );
line[n_bytes] = '';
char const* p = line;
finished = true;
while( char const input = *p++ )
{ 
if( input == 'n' )
{
finished = false;
break;
} 
printf( "[%c]", input );
}
printf( "n" );
}
}
auto main()
-> int
{
printf( "before shelln" );
shell();
printf( "shell has exitedn" );
}

离开让你解决以下问题:

  • 处理EOF(空行推送(
  • 根据C++iostreams而不是CFILE*i/o进行重写
  • 使用Ctrl+D推送的输入行,控制台输出中缺少换行符

注意1:read通常也可用于Windows编译器。然而,

注2:Ctrl+D用于推送当前行是Unix陆地约定。如果您希望您的程序无论如何运行或在什么系统上都能表现出这种行为,则必须使用一些可移植的低级别字符输入库,如ncurses。