不回车获得一个字符(UNIX和LINUX C++)

来源:互联网 发布:ktv软件下载 编辑:程序博客网 时间:2024/06/14 03:43

MS-DOS程序员在转到UNIX系统之后最先提出的问题之一就是“我如何在不按一下回车键的情况下从终端读取一个字符?”在UNIX中,终端输入 在缺省情况下是被“一锅端”的,也就是说整行输入是被一起处理的,这样行编辑字符(backspace , delete等)可以不通过正在运行的程序就能发挥作用。通常,这是一种人们希望的方便方法,但它也意味着在读入数据时必须按一下回车键表示输入行结束后 才能得到输入的数据。这种方法对于整行整行的输入是非常有效的,但有些程序需要在每按一键之后就得到这个字符,这就有些不方便了。这个“一次输入一个字符的”特性对于许多种类的软件来说都是非常重要的,但对于PC而言却是小菜一碟。C函数库支持这个特性,通常使用一个kbhit() 的函数,如果一个字符正在等待被读取,它就会发出提示。Microsoft ,Borland 的C编译器提供了了getch()(或getche(),它可以使字符在读取的同时回显在屏幕上来)来获取单个字符,而不用等整行结束。人们经常感到疑惑,为什么ANSI C 不定义一个标准的函数来获取一次按键后的字符。由于没有一种标准的方法,每个系统都采用了不同的方法,这们样便使程序失去了可移植性。反对将kbhit ()纳入标准的人认为:它在绝大多数情况下用于游戏软件的,而且还存在其他许多未标准化的终端I/O特性。另外,你可能并不想要一个在某些操作系统中很难 实现的标准库函数。赞成它的人则认为:它在绝大多数情况下用于游戏软件,而游戏编写者并不需要很多的标准化的其它终端I/O特性。不论你支持哪个观点,事 实上X3J11小组还是错过了一个使C语言成为一代学生程序员在UNIX上编写游戏的一种选择的机会(就是未吸纳这个特性)。在UNIX中,有两种方法可 以实现逐个字符的输入,一种很难,一种很容易。容易的方法就是让stty程序来实现这个功能。尽管它是一种间接实现的方法,但对程序而言并无大碍。 #include main() { int c; /*最初终端驱动处于普通的一次一行模式*/ system("stty raw"); /*使终端驱动处于一次一字符模式*/ c=getchar(); system("stty cooked"); /*使终端驱动回到一次一行模式*/ } 最后一行system("stty cooked");是必要的,因为程序结束后,终端字符驱动特性的状态将延续下去。在程序把终端设为一种滑稽的状态之后,如果不作修改,它就会始终处于这种模式。这和设置环境变量明显不同,后者在进程结束后自动消失。 把I/O设置为raw状态可以实现阻塞式读入(blocking read),如果终端没有字符输入,进程就一直等待,直到有字符输入为止。如果需要非阻塞式读入,可以使用ioctl()(I/O控制)系统调用。它提供 一个针对终端特性的良好控制层,可以告诉你在SVr4系统下是否有一个键被按下。下面的代码使用了ioctl(),这样只有当一个字符等待被读和时进程才 进行读取。这种类型的I/O被称为轮询,就好像不断地询问设备状态,看看它是否有字符要传给你。 #include int kbhit() { int i; ioctl(0,FIONREAD,&i); return i; } main() { int i=0; int c=' '; system("stty raw -echo"); printf("enter 'q' to quit: /n"); for(;c!='q';i++) { if(kbhit()) { c=getchar(); printf("/n got %c,on iteration %d",c,i); } } system("stty cooked echo"); } 原文网址:http://blog.csdn.net/Borenbao/archive/2006/09/13/1217365.aspx

原创粉丝点击