You normally can't read input a character at a time from the terminal because
that the terminal is configured to be in line-by-line mode by default, so that
the editing characters (like the backspace key) can be used by the user when
entering a line.

The man page for termio  discusses how to change the terminal settings to do 
things like put the terminal in character-by-character mode so that you can 
read each character as it is typed.  To view this man page, "man  termio".

Below is an example of how to use the functions described in that man page.
It is a function called "keypressed", which turns on character-by-character
mode, then uses another special function call (the FIONREAD ioctl call) to ask
the system how many characters are waiting to be read, then turns off
character-by-character mode (or, actually, puts it back to whatever it was
before the function started); the net result is a deter- mination of whether
or not a key has been pressed.  Note that this function would not work if it
did not turn on character-by-character mode, because FIONREAD would continue
to return 0 until the user hit return.

/* Procedure to check for waiting input on the tty.  Does not */
/* actually read the input.                                   */

#include 
#include 
#include 
#include 

int
keypressed()
{
     /* These are for ioctl */
     struct sgttyb tty, ntty;
     int ttyset, stat, arg;

     ttyset = 0;

     /*
      * The TIOCGETP ioctl call gets the tty information structure.
      * See tty(4) for details about the contents of that structure.
      */
     stat = ioctl(0, TIOCGETP, &tty);
     if (stat == -1) {
          perror("ioctl");
          return(-1);
     }

     /*
      * CBREAK is the status flag that controls character by character
      * input mode.  This if statement checks to see if CBREAK is
      * already enabled and only enables it if it is not.
      */
     if (! (tty.sg_flags & CBREAK)) {
          ntty = tty;
          ttyset = (! ttyset);
          /* OR'ing the status bits with CBREAK turns it on. */
          ntty.sg_flags |= CBREAK;
          /* TIOCSETN changes the terminal characteristics, without */
          /* discarding pending data.                               */
          stat = ioctl(0, TIOCSETN, &ntty);
          if (stat == -1) {
               perror("ioctl");
               return(-1);
          }
     }

     /* FIONREAD returns the number of characters of waiting input */
     stat = ioctl(0, FIONREAD, &arg);
     if (stat == -1) {
          perror("ioctl");
          return(-1);
     }

     if (ttyset) {
          /* put the tty characteristics back to their original form */
          stat = ioctl(0, TIOCSETN, &tty);
          if (stat == -1) {
               perror("ioctl");
               return(-1);
          }
     }

     return(arg);
}