Search code examples
c++casciikeystroke

Prettyprint ascii values for keystrokes in C/C++


When my program's user hits an unused key, even a key that lacks a viewable glyph, I want to report something like "Warning: ignoring keystroke Ctrl+W". That's kinder than "ignoring keystroke whose decimal value is 23; go google that yourself, doofus."

So, does C or C++ have any vaguely standard way to convert ints to strings, something like this?

65 -> "A"
141 -> "a"
32 -> "SPACE"
3 -> "CTRL+c"
26 -> "Ctrl+Z"

This many decades after the decline of EBCDIC, copypasting a table such as "man ascii" is just too embarrassing ( Ascii name of value ).


Solution

  • A classic problem.

    First we need to sort out ASCII values vs. keystrokes. ASCII is a character encoding with values 0 to 127. Keystrokes "codes" vary but usually map to ASCII when available (Shift + A makes ASCII code 97) and to other codes or actions for the other keys like F1, right arrow, etc. Typically a keyboard has more than 256 possible keystroke combinations. Further, some keyboard interfaces may directly generate Unicode which has over a million codes.

    As typically char is 8 bits (256 codes) and usually codes 0 to 127 as ASCII and the remainder very system dependent. The isprint() or isgraph() may be used to sort out the " viewable glyph" requirement. After that one may need to roll you own code.

    // Sample handler
    int keystroke = OP_GetKeystroke();  // fictitious system dependent function
    if (OP_IsChar(keystroke)) {
      char ch = keystroke;
      if (isascii(ch)) {
        if (isprint(ch)) {
          printf("%c", ch);
        }
        else if (ch < ' ') {
          printf("<Ctrl-%c>", ch+'@');
        }
        else {
          printf("<DEL>");
        }
      }
      else { 
        printf("<\x%02X>", ch & 0xFF);  // char codes outside ASCII range 
      }
    }
    else {
      printf("<Key: %X>", keystroke);  // keystroke outside char range 
      }
    

    isprint() true for ASCII codes 32 to 126.
    isgraph() true for the same codes as isprint() expect code 32 (space).
    This answer is problematic in non-ASCII environments.