【问题标题】:Detect Ctrl+d if input buffer is not empty using getchar()如果输入缓冲区不为空,则使用 getchar() 检测 Ctrl+d
【发布时间】:2018-07-24 21:06:53
【问题描述】:

我正在编写一个类似 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。使用 Ctrl+D 推动的行并非如此。
  • @Cheers:我如何确定不是\n 的字符是在行尾,还是行中还没有结束?
  • 你不能用stdio做这个,你需要使用低级输入函数。
  • stackoverflow.com/questions/7469139/… 解释了如何在不等待按下“Enter”的情况下读取字符
  • 有没有跨平台的解决方案?

标签: c++ console getchar


【解决方案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。

【讨论】:

  • 我的错,确实我按了 Ctrl D 两次。嗯!
  • @TaylorNichols 好的,通过使用 Unix-land read OS API 函数而不是 C fgets 来修复它。
猜你喜欢
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
  • 2022-01-17
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
相关资源
最近更新 更多