如何在按键后立即读取terminal的input缓冲区

我想阅读我的c程序中的箭头按键,并用其他stringreplace它们(立即在terminal本身)。 我正在试图在unixterminal中实现bash历史function。 我写了这个代码。

int main(int argc, char *argv[]) { char c; char str[1024]; int i = 0; while((c = fgetc(stdin)) != '\n'){ if(((int)c) == 27){ c=fgetc(stdin); c=fgetc(stdin); if (c == 'A') { printf("%c[A%c[2K",27, 27); printf("UP"); } } str[i++] = c; } printf("\n"); return 0; } 

但是,这不起作用,因为terminal等待换行符或EOF发送input缓冲区到标准input。 所以,我必须按回车键来分析用户input。

在这个答案中 ,用户提到使用system ("/bin/stty raw"); 但是这会取代所有的默认terminal行为(例如退格,删除等)。

那么,有没有什么方法可以直接读取/操作terminalinput缓冲区,如果检测到箭头按键,就可以调整缓冲区本身?

环境 – Ubuntu(Linux)

更新1:是否有一种方法来改变信号/中断(默认是按回车键),使terminal发送存储input到缓冲区? 这也可能帮助我实现相同的行为。

最终代码:

通过检查strace bash输出,我find了特定按键的ASCII字符

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #define ESCAPE '\33' #define BACKSPACE '\177' #define DELETE '~' int main(){ struct termios termios_p; struct termios termios_save; tcgetattr(0, &termios_p); termios_save = termios_p; termios_p.c_lflag &= ~(ICANON|ECHO); tcsetattr(0,TCSANOW, &termios_p); char buff; while(read(0, &buff, 1) >= 0){ if(buff > 0){ if(buff == ESCAPE){ read(0, &buff, 1); read(0, &buff, 1); if(buff == 'A'){ write(2, "up", 2); }else if(buff == 'B'){ write(2, "down", 4); }else if(buff == 'C'){ write(2, "\33[C", 3); }else if(buff == 'D'){ write(2, "\10", 2); } }else if(buff == BACKSPACE){ write(2, "\10\33[1P", 5); }else if(buff == DELETE){ write(2, "\33[1P", 4); }else{ write(2,&buff,1); } // write(2,&buff,1); if(buff == 'q'){ break; } } } tcsetattr(0,TCSANOW, &termios_save); return 0; } 

Solutions Collecting From Web of "如何在按键后立即读取terminal的input缓冲区"

看来你正在寻找这样的事情。

该程序实质上等待用户输入。 如果按向上箭头键,程序打印“箭头键按下”,然后退出。 如果按下其他任何东西,则等待用户完成他正在输入的内容并打印出来,然后退出。

 #include <termios.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main() { struct termios oldt, newt; char ch, command[20]; int oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); while(1) { ch = getchar(); if (ch == '\033') { printf("Arrow key\n"); ch=-1; break;} else if(ch == -1) // by default the function returns -1, as it is non blocking { continue; } else { break; } } tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); if(ch != EOF) { ungetc(ch,stdin);ith putchar(ch); scanf("%s",command); printf("\n%s\n",command); return 1; } return 0; } 

在我的Linux机器上,我使用ncurses:

 #include<stdio.h> #include<ncurses.h> void checkArrow(){ int ch; initscr(); raw(); keypad(stdscr, TRUE); noecho(); printw("Press q to Exit\t"); do{ switch(ch){ case KEY_UP: { printw("\n\nUp Arrow\n"); printw("Press q to Exit\t"); break; } case KEY_DOWN:{ printw("\n\nDown Arrow\n"); printw("Press q to Exit\t"); break; } case KEY_LEFT:{ printw("\n\nLeft Arrow\n"); printw("Press q to Exit\t"); break; } case KEY_RIGHT:{ printw("\n\nRight Arrow\n"); printw("Press q to Exit\t"); break; } } }while((ch = getch()) != 'q'); printw("\n\n\t\t\t-=GoodBye=-!\n"); refresh(); endwin(); } int main(){ checkArrow(); return 0; } 
 Up Arrow Press q to Exit 
 Down Arrow Press q to Exit Left Arrow Press q to Exit Right Arrow Press q to Exit