• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1215
  • Last Modified:

Unbuffered input from keyboard

When I use getchar() in my C programs, it does not get the characters as I type in.  It waits for a carriage return.  The function call setbuf(stdin, NULL) did not help.  What do I have to do so that the application program does not have to wait until the user types a carriage return ?
1 Solution
Try using getch() from curses.h
I don't have unix machine to test this. But I am sure that will work.
NathAuthor Commented:
This did not work.  It gives the following error messages:
undefined reference to stdscr
undefined reference to wgetch
did you link with -lcurses
A proven path to a career in data science

At Springboard, we know how to get you a job in data science. With Springboard’s Data Science Career Track, you’ll master data science  with a curriculum built by industry experts. You’ll work on real projects, and get 1-on-1 mentorship from a data scientist.

Below is a C++ program that demonstrates how to read single keys.

#include <stdio.h>
#include <sys/termio.h>   // for HP_UX
#include <unistd.h>
#include <sys/ioctl.h>

struct termio zap, original;

// Read a character (or none) from a file descriptor.
// min:     minumum number of characters that "read" is waiting // for
// timeout: maximum waiting time (in units of 0.1 second)
// Returns:
// -2 on error
// -1 if no key was pressed
// else keycode

int readOneCharacter (int fd, int min, int timeout) {

    unsigned char c;
    // Must be unsigned because we want to return character     // values in the
    // range 0..255.
    int count;
    int rc;
    // Modify termio
    zap = original;
    zap.c_cc [VMIN] = min;
    zap.c_cc [VTIME] = timeout;

    // ignore Ctrl-C (interrupt), Ctrl-Z (suspend) and Ctrl-\ (quit)
    zap.c_lflag = 0;

    // recognize Ctrl-C (interrupt), Ctrl-Z (suspend) and Ctrl-\         // (quit)
    // zap.c_lflag = ISIG;  

    // disable flow control (Ctrl-S, Ctrl-Q), do not convert CR to LF             // or vice versa.
    zap.c_iflag = 0;
    // Set new termio
    rc = ioctl (fd, TCSETA, &zap);
    if (rc == -1) {
        perror ("ioctl");
        return -2;

    // Read one char
    count = read (fd, &c, 1);
    if (count == -1) {
        // An error has occured
        perror ("read");
        return -2;
    } else if (count == 1) {
        // A key has been pressed. Return the key.
        return int (c);
    } else {
        // No key pressed.
        return -1;

// Wait for a key to be pressed. If the timeout expires and no // key was pressed, -1 is returned.
int kbGetKeyTimeout (int timeout) {
    return readOneCharacter (STDIN_FILENO, 0, timeout);

// Wait for a key to be pressed
int kbGetKey () {
    return readOneCharacter (STDIN_FILENO, 1, 0);

// If a key was pressed, then return it, otherwise return -1.
// Don't wait.
int kbGetKeyPressed () {
    return readOneCharacter (STDIN_FILENO, 0, 0);

NathAuthor Commented:
This program works.  But, it does not reset the original termio and, therefore, stays in the new mode after the function is called.  How do we reset the original termio ?
Oops, I forgot to paste the initialization stuff. Sorry! Here it is:

int main () {

    // Sanity check
    if  (!isatty (STDIN_FILENO)) {
        fprintf (stderr, "stdin: not a tty.\n");
        return 1;

    // Read termio
    ioctl (STDIN_FILENO, TCGETA, &original);

    // Now read the keys....
    // ....
    ... kbGetKey()  ....
    // ....

    // Restore original termio
    ioctl (STDOUT_FILENO, TCSETA, &original);

    return 0;

Both steps (read original termio, restore original termio) can also be performed at the beginning and the end of function "readOneCharacter", respectively. But if you plan to read more than a few keys, it is advisable to leave it in the main routine.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now