C++的getchar()函数:是否有待读取的数据?

4
我正在使用C/C++在Linux上实现一个键盘读取程序。我知道未经缓冲的getchar函数将返回键的少量数据值。对于所有ASCII键(a-z,A-Z,1-9,标点符号,回车,制表符和ESC),getchar()将返回单个值。对于其他键,例如箭头键,将读取ESC键,但是当再次调用getchar()时,它将获得另一个值(A、B、C或D)。
A = 65
B = 66
向上箭头 = 27 91 65
F5 = 27 91 49 53 126
ESC = 27
完整表格在此处 有没有办法检查是否有更多字符需要读取或只有一个字符?当读取键并且其第一个值为ESC时,我不知道它是以ESC开头的功能键还是仅为ESC键。
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <iostream>
#include <string>
#include <termios.h>
#include <unistd.h>

using namespace std;

int main(int argc, char *argv[]) {

    int ch[5];
    int i;
    struct termios term;

    tcgetattr( STDIN_FILENO, &term );
    term.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &term );

    ch[0] = getchar();

    // If ch[0] = 27 and there is more data in the buffer
    // printf("You pressed a function key");
    // Else
    // printf("You pressed ESC");

    return 0;   

}

2
你的目标操作系统是什么? - paddy
尝试在标准输入上使用read,并将标准输入的属性设置为非阻塞。读取直到它返回大小为0。 - bikram990
1
如果您输入超出ASCII字符集所包含的键 - 例如功能键或使用控制键与其他键组合 - 则返回值通常是无意义的。这些键超出了ANSI C定义,因此getchar()在处理这些键和/或键组合时的行为取决于系统。 - Dayal rai
@paddy 我正在使用Linux。 - Blue Ice
你考虑使用ncurses来进行输入吗?我相信它可以为你处理所有的ANSI代码。 - paddy
@paddy 我正在尝试只使用标准库。 - Blue Ice
3个回答

0

当你获得转义并尽可能多地读取时,可以将stdio标记为非阻塞。

你需要包含<fcntl.h>。

if (ch[0] == 27) {
    int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
    for (;;) {
        int c = getchar();
        if (c == EOF)
            break;
        printf("%u ", c);
    }
    fcntl(STDIN_FILENO, F_SETFL, flags);
    puts("\n");
}

在循环中连续读取两个键时仍然存在问题,因为循环会一直读取直到没有更多数据可用。


你需要在某个时刻调用 clearerr(stdin);否则所有后续的 getchar 调用都将返回 EOF... - Chris Dodd

0

在获取第一个ESC字符后,您可以读取其他字符而无需等待(例如通过在termios结构中设置c_cc [VMIN] = 0和c_cc [VTIME] = 0),然后如果找到的字符不匹配功能键模式,则将已读取的字符插入缓冲区以供读取。然后,在下一次获取时,首先返回缓冲的字符(如果有)。


-1

在循环中添加getchar(),并在输入的键为ENTER时退出循环。 例如:

char ch[5];
int i=0;
while(1)
{
   ch[i] = getchar();
   if('\n'==ch[i])
   {
     break;
   }
   i++;
   if(i==5)
   {
     break;
   }

}

你可能需要注意不要在ch缓冲区的末尾进行写入。 - Jason
如果您输入的字符超过5个,这将导致缓冲区溢出。 - Dietrich Epp
您可以使用std::vector来避免该问题。 - dutt
@akhil 请注意,我的问题中使用的是无缓冲输入。你的答案对于除五个序列键或回车以外的任何键的无缓冲输入都不能正确工作。 - Blue Ice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接