int main(int argc, char *argv[], char *env[])
{
printf("Press any key to exit.\n");
getch();
return 0;
}
根据手册页,
getch
应该等到按任意键
...但实际上它在按任意键之前直接返回。 (返回的值为-1
)。
为什么?
更新
我在Linux上。如果不使用Press any key to exit.
,我该如何实施getch()
?
getchar()
只会在按回车后返回,这不是我想要的。
答案 0 :(得分:12)
在Linux上,getch()
可能是curses
函数,它与同名的Windows特定函数完全不同。 curses
(ncurses
)对于您想要做的事情可能有点过分。
最简单的方法是等到用户按下 Enter ,你可以这样做:
int c;
printf("Press <enter> to quit: ");
fflush(stdout);
while ((c = getchar()) != '\n' && c != EOF) {
/* nothing */
}
如果您真的希望用户能够按任何键,而不仅仅是 Enter ,您可以执行以下操作:
system("stty cbreak -echo");
getchar();
system("stty cooked echo");
第二个stty
旨在将tty恢复到合理的设置(它应该将它们恢复到原来的状态,但保存和恢复状态会稍微复杂一些)。可能有更简洁的方法(使用stty
程序本身使用的任何库函数)。
编辑:在不等待 Enter 的情况下阅读单个字符是一个经常被问到的问题。事实上,它是comp.lang.c FAQ中的问题19.1。
EDIT2:我最近没有做过很多关于诅咒的工作,但我只是做了一些游戏。除非您先致电getch()
并且initscr()
清除屏幕,否则initscr()
似乎无效。 curses适用于需要完全控制显示的文本编辑器等应用程序。可能有一种方法可以在不控制屏幕的情况下使用getch()
,但我还没有找到它。
system("stty ...")
kludge实际上可能是最好的方法。
EDIT3:另一个答案中的termios
解决方案可能是最好的(system("stty ...")
更简单,但调用外部程序感觉有些过分。
关于OP的评论“我不敢相信Press any key to exit.
在c中做的很麻烦”,是的,这看起来确实很奇怪 - 但进一步认为它有正当理由。
查看典型Unix或Linux系统上安装的程序。我想你会发现很少有人需要这种输入(等待一次按键)。
许多程序使用命令行参数和从文件或stdin
读取的数据。用户键入的任何内容都是输入数据,而不是命令或对提示的响应。
某些程序会要求确认某些操作(apt-get
和cpan
等安装程序经常执行此操作) - 但他们通常会读取输入的行并检查第一个角色。或者,对于一些激烈的操作,他们可能会要求您输入整个单词“是”,然后输入 Enter (您不想重新格式化硬盘驱动器,因为您不小心碰到了密钥)。
当然很多程序(文本编辑器,文件查看器)都读取单字符非回显输入,但这些程序往往是基于curses的;他们控制整个终端窗口。
最后,许多程序都有GUI界面(Web浏览器等);他们甚至可能都没有从stdin读过。
大多数生产Unix程序不使用或需要Press any key to exit
提示。他们只是默默地做自己的工作,然后终止,这样你就可以做下一件事了。这种需求主要存在于相对基础的课程中,例如家庭作业。并不是家庭作业有任何问题,但整个系统并非主要用于支持这种用法。
答案 1 :(得分:6)
这是一个最小的例子
#include <curses.h>
int main(){
initscr();
cbreak();
noecho();
printw("Press any key to continue.");
refresh();
getch();
endwin();
return 0;
}
但似乎没有任何方法可以在不清除屏幕的情况下使用ncurses。 过度杀戮的污点,也许?!
修改强>
这是我工作的另一种方式。这不使用curses,也不清除屏幕。
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main() {
struct termios old,new;
tcgetattr(fileno(stdin),&old);
tcgetattr(fileno(stdin),&new);
cfmakeraw(&new);
tcsetattr(fileno(stdin),TCSANOW,&new);
fputs("Press any key to continue.",stdout);
fflush(NULL);
fgetc(stdin);
tcsetattr(fileno(stdin),TCSANOW,&old);
return 0;
}
该联机帮助页称cfmakeraw()可能不是完全可移植的。但它只是设置一大堆旗帜的简写:
Raw mode
cfmakeraw() sets the terminal to something like the "raw" mode of the old Version 7 terminal
driver: input is available character by character, echoing is disabled, and all special pro-
cessing of terminal input and output characters is disabled. The terminal attributes are set
as follows:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;