I know they don't have standard ASCII values, but how do you check for them?

I am making a command prompt-type interface for a text-based RPG a friend and I are making, and I would like to be able to use the arrow keys to navigate in menus.

I am using getch(); in a do-while loop. The exiting condition of the loop is the user hits ENTER. This loop just keeps putting chars (gotten from getch() ) into a char array, with 0D hex or '\n' being the char that the loop stops on. Just a real simple loop. I included the following line into my developmental program to see what the values are of the keys that you press:

printf("%c %d ", str[num], str[num]);

and when the UP arrow key is pressed, this line displays " 0 H 72", with " 0 H" being the value of the UP arrow key. This apparently doesn't look like it will fit into a char, so how would I code for it? Because I wrote a function that displayed the length of the string passed to it and it said the string length was 0 characters long. It looks like the UP arrow key has the value of 72, but this is incorrect, because capital h has this decimal value, which leads me to believe that there are possibly NULL characters in the " 0 H", because my function that returns the length of the string counts '\0' (or NULL) as the end of the string. At face value, this looks like the "string" is 4 characters long.

But if the first 'char' in it is not a space, and instead, actually a NULL character, then it would return 0 characters long just like it is doing.

So what do you recommend me doing to check to see if the user hits an arrow key? I would like it to work just like the command prompt in DOS or Windows...when the user hits left or right, it takes them left or right one character in the text they have entered on the line. And when they hit up or down, it takes them up or down one command in their command history.

Thanks, :)
Diode

Recommended Answers

All 19 Replies

Oops, I quickly realized that I was inaccurate in stating that the UP arrow key contained 4 characters. I forgot about that line of code I supplied which includes spaces and values.

The UP arrow key really contains: two characters. The first character is a NULL space, or '\0', and the second character is a capital h, 'H'.

Sorry for the mix up.

Diode :)

Nevermind, I figured it out.

But thanks anyway :)
Diode

Wait, wait! How did you do it, Diode?
(I don't mean to hijack the thread, but this is more efficient than posting
another thread asking the same thing, only to have Diode answer the question)

Ok let me whip up a simple program to demonstrate it. No point in pasting all my hundreds of lines of code for one trivial matter.

It will take me a little while to make a simple program but I will post it in a short while.

:)
Diode

I usually do it with this:

if (kbhit())
{
    ch1 = getch();
    if (ch1 != '\0')
    {
            // process a normal keystroke
    }
    else
    {
        ch2 = getch();    // get the arrow or function key
        switch(ch2)
        {
                // process the arrow or function key
        }
    }
}

You can use this to discover what the key values are.

This only works for compilers that have getch() and kbhit() defined, of course.

This compiled with no errors on Borland C++ 5 and gcc. So this should compile on yours.

/******************************* 0026.c *******************************/
/*                                                                    */
/* Date:        September 22, 2006                                    */
/* Author:      diode                                                 */
/*              ndweiler@mchsi.com                                    */
/* Purpose:	    To practice checking for arrow keys being pressed     */
/*              in a header file                                      */
/*                                                                    */
/**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <process.h>
#include <ctype.h>

#define STRING_LENGTH 100
#define ARROW_KEY_NONE 0
#define ARROW_KEY_UP 1
#define ARROW_KEY_DOWN 2
#define ARROW_KEY_LEFT 3
#define ARROW_KEY_RIGHT 4
#define ARROW_KEY_POSSIBLE 5

// BEGINNING OF PROTOTYPES

void settext(void);
void getline(char * str2);
void showoutput(char * str2);
int checkarrowkey(char key);

// BEGINNING OF PROGRAM

int main()
{
  char strexit[STRING_LENGTH];
  char strquit[STRING_LENGTH];
  char holdtextline[STRING_LENGTH];

  system("cls");
  holdtextline[0] = '\0';
  getline(holdtextline);
  showoutput(holdtextline);
  printf("\n");

  return 0;
}
// END OF PROGRAM

// BEGINNING OF FUNCTIONS

void settext(void)
{
  char text;
  text = getch();                           // holds the output on screen
}

void getline(char * str2)
{
  char str1[STRING_LENGTH];
  int num = 0;
  int checkkey = 0;                         // used to check for special keys

  printf("Enter your text:");               // instructs you to enter something

  do                                        // starts loop for input
  {
    if (num == STRING_LENGTH)
      {
        break;                              // exits when the string fills up
      }
      else
        {
          str1[num] = getch();              // puts a char into 'str'
        }

    if ((str1[num] == '\b') && (num <= 0))  // starts the backspace handler
    {                                       // if you're at the beginning...
                                            // do nothing
    }
    else                                    // but if everything's alright...
      {

/////////////////////////////////////////////////////////////////
// This is where I check to see if the user typed an arrow
/////////////////////////////////////////////////////////////////
        if((str1[num] == '\0') && (num >= 0))
          {
            num++;
            goto last;
          }
          else
            {
              if((num > 0) && (str1[num - 1] == '\0') && (str1[num] != '\0'))
                {
                  checkkey = checkarrowkey(str1[num]);

                  switch(checkkey)
                  {
                    case ARROW_KEY_UP:
                      printf("\nYou pressed the UP arrow key!");
                      return;

                    case ARROW_KEY_DOWN:
                      printf("\nYou pressed the DOWN arrow key!");
                      return;

                    case ARROW_KEY_LEFT:
                      printf("\nYou pressed the LEFT arrow key!");
                      return;

                    case ARROW_KEY_RIGHT:
                      printf("\nYou pressed the RIGHT arrow key!");
                      return;

                    default:
                      return;
                  }
                }
            }

/////////////////////////////////////////////////////////////////
// This ends where I check to see if the user typed an arrow
/////////////////////////////////////////////////////////////////

        printf("%c", str1[num]);            // echoes your char to the screen
      }

    str1[num] = tolower(str1[num]);         // converts it to lowercase

    if ((str1[num] == '\b') && (num >= 1))  // removes the last-typed char
      {                                     // from the screen and from the
        printf(" \b");                      // string
        str1[num - 1] = '\0';               //
        num = num - 1;                      //
      }
    else
      {
        if (str1[num] != '\b')              // if everything is alright...
          {                                 //
            num++;                          // it increments 'num' by 1
          }
      }

last:

  } while(str1[num-1] != 0x0D);             // loops until ENTER is hit

  str1[num - 1] = '\0';                     // create the NULL string char

  strcpy(str2, str1);                       // copy 'str1' to 'str2'
}

void showoutput(char * str2)      // beginning of 'showoutput'
{
  int length = strlen(str2);                // sets 'length' to the length of
                                            // the string 'str2'

  printf("\n\nYour text was '%s' ", str2);  // outputs 'str2' to screen


  printf("\n'%s' is %d characters long",// outputs 'str2' and its
         str2, length);                 // length to the screen
}

int checkarrowkey(char key)
{
  int whichkey = 0;
  char str1 = '\0';
  //char str2[STRING_LENGTH];

  str1 = key;

  switch(str1)
    {
      case 'H':
        whichkey = ARROW_KEY_UP;
        return whichkey;

      case 'P':
        whichkey = ARROW_KEY_DOWN;
        return whichkey;

      case 'K':
        whichkey = ARROW_KEY_LEFT;
        return whichkey;

      case 'M':
        whichkey = ARROW_KEY_RIGHT;
        return whichkey;

      default:
        return 0;
    }
}

I hope this was helpful to some people.

Cheers, :D
Diode

Oops, I forgot to delete the #define ARROW_KEY_NONE and #define ARROW_KEY_POSSIBLE constant declarations. This was when I was fooling around trying to figure it out, and just forgot to delete it.

:)

Diode

Oh and in regards to the title of my file, that is not how many programs I attempted before I figured it out, lol! It is the amount of programs I have compiled since Monday. Just noticed that I included that as well. Heh.

:)

Diode

I usually do it with this:

if (kbhit())
{
    ch1 = getch();
    if (ch1 != '\0')
    {
            // process a normal keystroke
    }
    else
    {
        ch2 = getch();    // get the arrow or function key
        switch(ch2)
        {
                // process the arrow or function key
        }
    }
}

You can use this to discover what the key values are.

This only works for compilers that have getch() and kbhit() defined, of course.

What is the top decimal value that kbhit() catches when you hit a key? I didn't know about kbhit. So I coded the entire thing from scratch. It works. But the UP arrow key for example is " H", that is: NULL, capital h. It is actually 2 characters. Does kbhit() catch 2 characters? And could you provide a sample program that prints on the screen that an arrow key was hit, like I coded my sample program? I am curious about this apparent quick way that you provided.

Thanks, :)
Diode

What is the top decimal value that kbhit() catches when you hit a key? I didn't know about kbhit. So I coded the entire thing from scratch. It works. But the UP arrow key for example is " H", that is: NULL, capital h. It is actually 2 characters. Does kbhit() catch 2 characters? And could you provide a sample program that prints on the screen that an arrow key was hit, like I coded my sample program? I am curious about this apparent quick way that you provided.

kbhit() doesn't catch characters. It returns TRUE if a key has been pressed, FALSE if no key is waiting. That way your program can do whatever processing it needs and not wait for a key. In effect it makes the keyboard interrupt driven. Leave out the kbhit() call if you don't need to test for keyboard readyness.

As for a sample program, just output the value of the int egers ch1 and ch2.

commented: rep++ Salem +3

Okay, so what libraries are getch() and kbhit() included in? (I think I might test this one out, after I reformat my computer...)

Okay, so what libraries are getch() and kbhit() included in? (I think I might test this one out, after I reformat my computer...)

In conio.h but this is not standard so there are posibility that you don't have this library.

diode, I ran your code in Dev-C++, and I found one error, last: didn't have anything happen, so I put in a nonsense integer declaration.

Also, when I ran it, if I press an arrow key, it displays a lowercase alpha, then the letter you defined. It doesn't detect that an arrow key was pressed (it doesn't say, "You pressed the [insert key here] key!"). I don't know, maybe Dev-C++ does something different. I haven't attempted to look through all of the code yet; it's a little late (early?) and I am not that great at C++ yet.
[EDIT] Wait! you used a lot of c libraries, no wonder, I haven't dealt with those at all... [/EDIT]

Anyways, I was hoping maybe you could explain this error I encountered.

diode, I ran your code in Dev-C++, and I found one error, last: didn't have anything happen, so I put in a nonsense integer declaration.

Also, when I ran it, if I press an arrow key, it displays a lowercase alpha, then the letter you defined. It doesn't detect that an arrow key was pressed (it doesn't say, "You pressed the [insert key here] key!"). I don't know, maybe Dev-C++ does something different. I haven't attempted to look through all of the code yet; it's a little late (early?) and I am not that great at C++ yet.
[EDIT] Wait! you used a lot of c libraries, no wonder, I haven't dealt with those at all... [/EDIT]

Anyways, I was hoping maybe you could explain this error I encountered.

Sorry, I just now found your reply. I haven't messed with this program for a long time. In fact, I forgot all about it. I've moved on to working with (as much as possible) ANSI standard C, and now I am moving onto C++. Sorry if I wasn't more help.

BTW, about your sig, I didn't know Ozzy Osbourne said that, but that is also on a Magic: the Gathering card, though I forget which one.

I usually do it with this:

if (kbhit())
{
    ch1 = getch();
    if (ch1 != '\0')
    {
            // process a normal keystroke
    }
    else
    {
        ch2 = getch();    // get the arrow or function key
        switch(ch2)
        {
                // process the arrow or function key
        }
    }
}

You can use this to discover what the key values are.

This only works for compilers that have getch() and kbhit() defined, of course.

please explain your code

please explain your code

getch() returns 0 when one of the special keys is pressed, such as one of the Function or arrow keys. When that happens the program has to call getch() again which will return the key code of the key that was pressed. The reason for this behavior is that special keys have the same key codes as other normal keys, and the program needs some way to distinguish them. When I write such programs I normally make those key codes negative values so that the rest of the program can easily distintuish between normal and special keys. Other programmers have added 255 to the value, which works ok too.

****(1)*****

#include<stdio.h>
#include<conio.h>

void main()
{
char c;
clrscr();
printf("Press \"Esc\" to exit");
gotoxy(1,10);
c=getch();
 while(c!=27)
 {
  if(c==0)
  {
  c=getch();
  gotoxy(1,10);
  clreol();
  printf("This key has two ascii values: 0 and %d",c);
  }
  else
  {
  gotoxy(1,10);
  clreol();
  printf("%d",c);
  }
 c=getch();
 }
}

************

*****(2)******

#include<stdio.h>
#include<conio.h>

void main()
{
char c;
int x=1,y=1;
clrscr();
for(y=1;y<17;y++)
{
gotoxy(52,y);
printf("|");
}
gotoxy(1,16);
printf("___________________________________________________/");
gotoxy(1,19);
printf("Press \"Esc\" to exit\n\n");
printf("Use arrow keys to move cursor");
x=1;
y=1;
gotoxy(x,y);
c=getch();
 while(c!=27)
 {
  if(c==0)
  {
  c=getch();
   if(c==77)
   {
    if(x==51)
    {
    x=1;
    gotoxy(x,y);
    }
    else
    {
    x++;
    gotoxy(x,y);
    }
   }

   if(c==75)
   {
    if(x==1)
    {
    x=51;
    gotoxy(x,y);
    }
    else
    {
    x--;
    gotoxy(x,y);
    }
   }

   if(c==80)
   {
    if(y==15)
    {
    y=1;
    gotoxy(x,y);
    }
    else
    {
    y++;
    gotoxy(x,y);
    }
   }

   if(c==72)
   {
    if(y==1)
    {
    y=15;
    gotoxy(x,y);
    }
    else
    {
    y--;
    gotoxy(x,y);
    }
   }
  }

  else if(c==8)
  {
   if(x==1)
   {
   x=51;
   gotoxy(x,y);
   }
   else
   {
   x--;
   gotoxy(x,y);
   }
  }

  else
  {
   if(x==51)
   {
    if(y==15)
    {
    y--;
    }
   x=x-50;
   y++;
   gotoxy(x,y);
   }
   else
   {
   printf("%c",c);
   x++;
   }
  }
 c=getch();
 }
}

************

Compiler: Borland's Turbo C++ (Version 3.0)

Special keys(arrow keys,function keys,delete,home,page up,end,....etc) have ascii values but
they have TWO ascii values, and thats why we have to use getch() TWICE
to sense them.
I have NOT used kbhit(), but I got the idea of using getch()
TWICE for special keys from WaltP's post, Thanx WaltP.

commented: bump two-year-old thread -5

Add.......

else if(c==13)
  {
  gotoxy(x,y);
  }

****(2)*****

void main()
{
...
...
while(c!=27)
{
  if(c==0)
  {
  }

  else if(c==8)
 {
 }

 >> H E R E <<

 else
 {
 }
c=getch();
}
}

...before running the code, Thank you.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.