Why does getch () return before pressing any key?

int main(int argc, char *argv[], char *env[]) { printf("Press any key to exit.\n"); getch(); return 0; } 

According to the manual page,

getch must wait for any key to be pressed

... but in fact it comes back just before pressing any key. (The return value is -1 ).

Why?




Update

I am on Linux. How can I implement Press any key to exit. if not use getch() ?

getchar() will only return after pressing Enter, this is not what I want.

+9
c linux getch
Sep 14 '11 at 1:52
source share
2 answers

On Linux, getch() is probably a curses function, which is very different from the same function as on Windows. curses ( ncurses ) is probably too large for what you want to do.

The easiest way is to wait for the user to press Enter , which you can do as follows:

 int c; printf("Press <enter> to quit: "); fflush(stdout); while ((c = getchar()) != '\n' && c != EOF) { /* nothing */ } 

If you really want the user to be able to press any key, not just Enter , you can do something like this:

 system("stty cbreak -echo"); getchar(); system("stty cooked echo"); 

The second stty designed to restore tty to reasonable settings (it should really restore them, whatever they are, but saving and restoring the state is a bit more complicated). There are probably cleaner ways to do this (using any library functions that the stty program itself).

EDIT: Reading a single character without waiting for Enter is a frequently asked question. Actually, question 19.1 in comp.lang.c is a frequently asked question .

EDIT2: I haven't worked with curses a lot recently, but I just played a little with it. It seems that getch() will not work unless you first call initscr() - and initscr() clears the screen. curses is intended for use with applications such as text editors that require full control over the display. There may be a way to use getch() without control of the screen, but I did not find it.

Most preferred may be the kludge system("stty ...") .

EDIT3: The termios solution in another answer is probably better ( system("stty ...") simpler, but calling an external program seems redundant.

Regarding OP's comment: β€œI can't believe that Press any key to exit. Is so troublesome to do in c”, yes, it seems strange, but, further on, there are good reasons for this.

Take a look at the programs installed on a typical Unix or Linux system. I think you will find that very few of them require such input (in anticipation of a single keystroke).

Many programs work with command line arguments and data read from files or from stdin . All that the user enters is the data entered, not the commands or answers to the prompts.

Some programs ask for confirmation for some actions (usually installers like apt-get and cpan ), but usually read the input line and check the first character. Or, for some radical actions, they may require you to type the whole word β€œyes” and then Enter (you do not want to reformat the hard drive because you accidentally pressed a key).

Of course, many programs (text editors, file viewers) read single-character non-echo data, but such programs are usually based on curses; they take control of the entire terminal window.

Finally, a number of programs have GUIs (web browsers, etc.); they probably don’t even read from stdin.

Most production Unix programs do not use or do not need Press any key to exit queries. They just do their job, often silently, and then stop working, so you can do the following. The need exists mainly for relatively elementary programs, such as homework. Not that there is something wrong with homework, but the system as a whole is not intended primarily to support such use.

+12
Sep 14 '11 at 2:29
source share

Here is a minimal example

 #include <curses.h> int main(){ initscr(); cbreak(); noecho(); printw("Press any key to continue."); refresh(); getch(); endwin(); return 0; } 

But there seems to be no way to use ncurses without clearing the screen. Spot Overkill, maybe ?!

Edit

Here is another way that I worked. It does not use curses and does not clear the screen.

 #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; } 

The manpage says cfmakeraw () may not be fully portable. But this is just a shorthand for setting a mess of flags:

 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; 
+6
Sep 14 2018-11-11T00:
source share



All Articles