Thread: How do you get a single character in C without pressing the return key?

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    55

    How do you get a single character in C without pressing the return key?

    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    
    
    
    
    /* System dependent key codes */
    enum
    {
      KEY_ESC     = 27,
      ARROW_UP    = 256 + 72,
      ARROW_DOWN  = 256 + 80,
      ARROW_LEFT  = 256 + 75,
      ARROW_RIGHT = 256 + 77
    };
    
    
    static int get_code ( void )
    {
      int ch = getch();
    
    
      if ( ch == 0 || ch == 224 )
        ch = 256 + getch();
    
    
      return ch;
    }
    
    
    int main ( void )
    {
      int ch;
    
    
      while ( ( ch = get_code() ) != KEY_ESC ) {
        switch ( ch ) {
        case ARROW_UP:
          printf ( "UP\n" );
          break;
        case ARROW_DOWN:
          printf ( "DOWN\n" );
          break;
        case ARROW_LEFT:
          printf ( "LEFT\n" );
          break;
        case ARROW_RIGHT:
          printf ( "RIGHT\n" );
          break;
        }
      }
    
    
      return 0;
    }
    I have this code that bitmaps for arrow keys, but I'm not sure how to do this with even more characters. I understand the switch statement and know what all the special keywords/statements do in this code. I'm just confused on how exactly one finds out how to map this, or if I could just somehow translate extended ASCII sets/ regular characters ( e.g. 65 = 'A' ). Also I know usually regular ASCII ends at 255, so what is with the 256( why does it get added to the getch() function and why is it that number)? Also, is this a good way of doing it, or should I use a more standard way?

  2. #2
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    Oh, and, before I get replies like, " how did you make this the first time then? ", I got this off of the website's FAQ for C programming.

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I'm just confused on how exactly one finds out how to map this,
    The answer is no one does. The safest thing is to use a library that can help you read special keys: preferably one that comes with constants like the ones used in the sample.

    or if I could just somehow translate extended ASCII sets/ regular characters ( e.g. 65 = 'A' ).
    No. Arrow keys are not part of ASCII, in any way, shape, or form.

    Also I know usually regular ASCII ends at 255, so what is with the 256( why does it get added to the getch() function and why is it that number)? Also, is this a good way of doing it, or should I use a more standard way?
    Reading special keys is in the realm of platform specific code.

    As to why is it that number, well it needed to be some number, or the key would be indistinguishable from others. The actual value is of little significance. The getch() that you are using comes from a really old library, so it isn't really a good way of doing it. People only continue to support it as a crutch for older code than you. Consider reading: Using Keyboard Input (Windows) instead. Of particular interest on that page is the section on processing keystroke messages. The information at that link is just as platform specific but it uses the (newer, relative to the getch function) Windows API.

    I think it is a waste of time to try understanding this particular method that you found, but I'll tell you anyway. The first getch() reads the part of the input generated by an arrow key that tells the system it is a special key. Then the second getch() reads the part of the input that distinguishes which special key it is. You would program a response under each specific circumstance you care about.
    Last edited by whiteflags; 05-31-2013 at 07:27 PM.

  4. #4
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Excellent question

    To understand what the code does, read the documtation of getch(): _getch, _getwch, _getch_nolock, _getwch_nolock (CRT)

    Quote Originally Posted by MSDN
    When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.
    So for example, if you press the down arrow, the program receives two keystrokes. The first is 0xe0 (which is 224). The second is 80.
    In normal ASCII, (Ascii Table - ASCII character codes and html, octal, hex and decimal chart conversion) 80 corresponds to 'P'. The 224 before the 80 tells you that you're receiving a special character.
    The reason the code adds it to 256 is to make sure the code return from get_code doesn't correspond to a normal ASCII character. So you could have in your switch statement:
    Code:
      case ARROW_DOWN:
         printf("DOWN");
         break;
      case 'P':
        printf("Normal P");
        break;
    and it would work. Basically the function creates a single unique number for regular characters and characters that need two codes.

    So how do you know what 'magic number' corresponds to what key?

    Searching MSDN yielded this: Key Scan Codes
    It seems to have the correct values for the keys you've already got in your program. In the "ASCII or extended" column, if it has E0 then E0 is read before the character value, and if it says 'NUL' then 0 is read before the character value. Looks good, but it's a reference for a 15 year old version!

    The MSDN description of keypress -> scan code -> virtual key -> character code (About Keyboard Input (Windows)) is worth reading.

    What getch() does for scan codes that do not match up to characters should be clearly documented in the getch() documentation. The fact that it's not is perhaps due to its age.

    Knowing that getch() is just turning scan codes into something else, you could go look at the source code for the values. It's in <msvc install dir>\VC\crt\src\getch.c. E.g.

    Code:
            { 81, { 224,  81 }, { 224,  81 }, { 224, 118 }, {   0, 161 } },
    Scan code 81 is Page Down. The braced numbers are the characters returned for Page down, shift+page down, ctrl+page down, alt+page down.

    However, using numbers found like this (or from obsolete documentation) is a Bad Thing. #defining them to something, or putting them in an enum, does not make it any better. Tool/library providers can change things that are undocumented without warning or explanation -- although something this old is unlikely to change (would break lots of people's code), it's a habit to avoid. I know it's not originally your code - but worth saying.

    The only reason I suggest looking at the source code for getch() is that it should provide you with some ideas on how to do this in a less archaic way without any 'magic numbers'.

    Some websites I found useful while researching this:
    Excellent blog series on keyboard layouts and scanning available keys. In C#, but much of the functionality exists in C++
    Scancodes explanation and tablesl
    kbd.h - some actual mappings between scan codes and virtual keys for common US keyboards

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to loop a single character?
    By spcx in forum C Programming
    Replies: 4
    Last Post: 08-23-2011, 10:54 PM
  2. Need help with Single Character
    By larry_2k4 in forum C Programming
    Replies: 2
    Last Post: 10-05-2010, 01:29 AM
  3. Replies: 12
    Last Post: 04-07-2007, 11:11 AM
  4. How to get single character input without pressing return
    By Mr. Flibble in forum C++ Programming
    Replies: 6
    Last Post: 10-06-2006, 08:55 AM
  5. get single character from string
    By deltaxfx in forum C Programming
    Replies: 7
    Last Post: 01-06-2006, 01:21 PM