Question 19.1

How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?


Alas, there is no standard or portable way to do these things in C. Concepts such as screens and keyboards are not even mentioned in the Standard, which deals only with simple I/O ``streams'' of characters.

At some level, interactive keyboard input is usually collected and presented to the requesting program a line at a time. This gives the operating system a chance to support input line editing (backspace/delete/rubout, etc.) in a consistent way, without requiring that it be built into every program. Only when the user is satisfied and presses the RETURN key (or equivalent) is the line made available to the calling program. Even if the calling program appears to be reading input a character at a time (with getchar or the like), the first call blocks until the user has typed an entire line, at which point potentially many characters become available and many character requests (e.g. getchar calls) are satisfied in quick succession.

When a program wants to read each character immediately as it arrives, its course of action will depend on where in the input stream the line collection is happening and how it can be disabled. Under some systems (e.g. MS-DOS, VMS in some modes), a program can use a different or modified set of OS-level input calls to bypass line-at-a-time input processing. Under other systems (e.g. Unix, VMS in other modes), the part of the operating system responsible for serial input (often called the ``terminal driver'') must be placed in a mode which turns off line-at-a-time processing, after which all calls to the usual input routines (e.g. read, getchar, etc.) will return characters immediately. Finally, a few systems (particularly older, batch-oriented mainframes) perform input processing in peripheral processors which cannot be told to do anything other than line-at-a-time input.

Therefore, when you need to do character-at-a-time input (or disable keyboard echo, which is an analogous problem), you will have to use a technique specific to the system you're using, assuming it provides one. Since comp.lang.c is oriented towards topics that C does deal with, you will usually get better answers to these questions by referring to a system-specific newsgroup such as comp.unix.questions or comp.os.msdos.programmer, and to the FAQ lists for these groups. Note that the answers are often not unique even across different variants of a system; bear in mind when answering system-specific questions that the answer that applies to your system may not apply to everyone else's.

However, since these questions are frequently asked here, here are brief answers for some common situations.

Some versions of curses have functions called cbreak, noecho, and getch which do what you want. If you're specifically trying to read a short password without echo, you might try getpass. Under Unix, you can use ioctl to play with the terminal driver modes (CBREAK or RAW under ``classic'' versions; ICANON, c_cc[VMIN] and c_cc[VTIME] under System V or POSIX systems; ECHO under all versions), or in a pinch, system and the stty command. (For more information, see <sgtty.h> and tty(4) under classic versions, <termio.h> and termio(4) under System V, or <termios.h> and termios(4) under POSIX.) Under MS-DOS, use getch or getche, or the corresponding BIOS interrupts. Under VMS, try the Screen Management (SMG$) routines, or curses, or issue low-level $QIO's with the IO$_READVBLK function code (and perhaps IO$M_NOECHO, and others) to ask for one character at a time. (It's also possible to set character-at-a-time or ``pass through'' modes in the VMS terminal driver.) Under other operating systems, you're on your own.

(As an aside, note that simply using setbuf or setvbuf to set stdin to unbuffered will not generally serve to allow character-at-a-time input.)

If you're trying to write a portable program, a good approach is to define your own suite of three functions to (1) set the terminal driver or input system into character-at-a-time mode (if necessary), (2) get characters, and (3) return the terminal driver to its initial state when the program is finished. (Ideally, such a set of functions might be part of the C Standard, some day.) The extended versions of this FAQ list (see question 20.40) contain examples of such functions for several popular systems.

See also question 19.2.

References: PCS Sec. 10 pp. 128-9, Sec. 10.1 pp. 130-1
POSIX Sec. 7


Read sequentially: prev next up top


This page by Steve Summit // Copyright 1995 // mail feedback