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

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

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

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

#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() 仅 returns EOF。按 Ctrl+d 中线会导致 getchar() 到 return 每个缓冲字符 除了 EOF 字符本身。

如何判断Ctrl+d是否按下中线?

我考虑过使用超时。在此方法中,如果 getchar() 在 return 换行以外的内容后暂停太久,解释器会假定 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] = '[=10=]';

        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。