今天看到一份shell源码,其中有用到不输入回车即可收到字符的功能,在这份源码中,它的作用是在shell中接收上下键,执行历史命令。
原始代码:
/* 如何实现不用回车,就能读取一个字符,此程序可以用来查看键盘的字符编码 */ /* 以“上方向键”为例,3个字符分别是27<esc>, 79<O>,和65<A>。A> 而上面的getch()函数中的read()函数1次只从标准输入读入1个字符, 所以在getch()读入1个字符返回后再次被调用时,标准输入的缓冲区中还有2个字符, 因此read()函数不会阻塞(尽管我们这时没有再按下任何键),而是读出第2个字符, 然后返回,然后又继续读入第3个字符。 所以按下1个方向键,getch()函数实际上被调用了3次。 */ #include<stdio.h> #include<termio.h> #include<stdlib.h> static struct termios tty; void set_key(); void reset_key(); char getch(); main() { char a; set_key(); while(1) { a=getch(); printf("%d%c/n",a,a); if(a=='0') break; } reset_key(); } void set_key() { struct termios new_tty; tcgetattr(0,&tty); new_tty=tty; new_tty.c_lflag&=~(ICANON|ECHO|ISIG); new_tty.c_cc[VTIME]=0; new_tty.c_cc[VMIN]=1; tcsetattr(0,TCSANOW,&new_tty); return; } void reset_key() { tcsetattr(0,TCSANOW,&tty); return; } char getch() { int i; char ch; switch(i=read(0,&ch,1)) { case -1: printf("error/n"); exit(3); case 0: printf("error0/n"); exit(4); } return(ch); }
升级版:
/* 改进版不用输入回车,自动获取字符, 这段代码的功能是屏蔽掉其它按键的输入,只接收ESC, 回车以及四个方向键的输入,并且显示用户的输入。如果用户按下ESC键,程序就会结束。*/ #include <stdio.h> #include <termio.h> static struct termios tty; enum Key{None, KeyESCClick, KeyEnterClick, KeyUpClick, KeyDownClick, KeyLeftClick, KeyRightClick}; void set_key(); void reset_key(); enum Key getch(); int main(int argc, char *argv[]) { enum Key a; set_key(); while(1) { a=getch(); switch(a) { case KeyESCClick: printf("esc/n"); reset_key(); return 0; case KeyEnterClick: printf("enter/n"); break; case KeyUpClick: printf("up/n"); break; case KeyDownClick: printf("down/n"); break; case KeyLeftClick: printf("left/n"); break; case KeyRightClick: printf("right/n"); break; default: break; } } reset_key(); return 0; } void set_key() { struct termios new_tty; tcgetattr(0,&tty); new_tty=tty; new_tty.c_lflag&=~(ICANON|ECHO|ISIG); new_tty.c_cc[VTIME]=0; new_tty.c_cc[VMIN]=1; tcsetattr(0,TCSANOW,&new_tty); return; } void reset_key() { tcsetattr(0,TCSANOW,&tty); return; } /* 修改了getch函数,由于上下左右方向键的字符编码特殊,所以在read中如果一次读取只有一个字符,那么就是普通字符, 如果是三个字符,那么就是方向键,再通过判断最后一个字符的内容就可以确定是方向键中的那一个。 */ enum Key getch() { int i; char ch[3]; while((i = read(0, ch, 3)) != -1) { printf("get char num: %d/n", i); switch(i) { case 1: switch(ch[0]) { case 0x1b: return KeyESCClick; case 0x0a: return KeyEnterClick; } break; case 3: switch(ch[2]) { case 'A': return KeyUpClick; case 'B': return KeyDownClick; case 'C': return KeyRightClick; case 'D': return KeyLeftClick; } } } return None; }
Copyright @ 2024 SunBo Powered by .NET 8.0 on Kubernetes Powered by: .Text and ASP.NET Theme by: .NET Monster