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

时间:2018-07-24 21:06:53

标签: c++ console getchar

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

  • 如果按下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

我已经考虑过使用超时。在这种方法中,如果Ctrl+d在返回换行符以外的内容后暂停太长时间,则解释器假定按下了getchar()。这不是我最喜欢的方法,因为它需要线程化,引入了延迟,并且尚不清楚适当的等待时间。

1 个答案:

答案 0 :(得分:1)

在常规行的末尾有一个'\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] = '\0';

        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 shell\n" );
    shell();
    printf( "shell has exited\n" );
}

让您解决以下问题:

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

注1:read通常也可用于Windows编译器。但是,

注意2:用于推送当前行的 Ctrl + D 是Unix领域的约定。如果您希望您的程序在不考虑其运行方式或运行于哪个系统上的情况下都表现出该行为,则必须使用一些可移植的低级字符输入库,例如ncurses。