1

I am compiling and executing my programs in cygwin on a windows computer. I am quite inexperienced in C but I would like a way to detect if a key has been pressed without prompting the user(e.g me). My pseudo code with desirable functions is shown below.

char ch;
while(1){
    if(KeyBeenPressed()){
    //a key has been pressed before getting here
        ch=getKeyPressed();
        if(ch=='0'){
            printf("you have pressed 0");
        }
        else{
            printf("you did't press key 0");
        }
    }

//do other stuff
} 

And my own try to solving this after searching the web is shown below.

#include <stdio.h>
#include <conio.h>
char ch;
void main(){
    while(1){
        if(kbhit()){ //kbhit is 1 if a key has been pressed
            ch=getch();
            printf("pressed key was: %c", ch);
        }
    }
}

A problem with this code is that the conio.h file can't be found(and I haven't found any other way to solve this). Apparently gcc compilers can't handle conio.h(I have attached the link to were it stood). http://www.programmingsimplified.com/c/conio.h

So I wonder if any of you guys know a way to detect if a key has been pressed in C, I would also like to retrieve the pressed key preferably in a char (I plan on using 0-9 for this application). The important thing is that the program can't wait until a key is pressed.

I am thankful for any suggestions that could solve this! Best regards Henrik

Lee Duhem
  • 14,695
  • 3
  • 29
  • 47
Henrik
  • 405
  • 1
  • 8
  • 19

2 Answers2

4

I use the following function for kbhit(). It works fine on g++ compiler in Ubuntu.

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    return 1;
  }

  return 0;
}
Shashwat Kumar
  • 5,159
  • 2
  • 30
  • 66
  • This code works really nice. But I would like to know what is happening from tcgetattr(STDIN_FILENO, &oldt); to fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); I will try to find it myself but I would appreciate an explanation if you have time. Thanks for the help! //Henrik – Henrik Mar 05 '14 at 07:57
  • tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); – Henrik Mar 05 '14 at 07:57
  • I tried to find the complete meaning of the statements after you asked. Generally, getchar() is blocking, i.e. wait for user input and proceeds after user press 'ENTER' key. So tcgetattr and tcsetattr are used to get input from terminal without needing to press 'ENTER' key. tcgetattr fetch current setting of terminal in oldt. tecsetattr set new setting of terminal. fcntl is used to take non-blocking input from stdin. After character is read, tcsetattr and fnctl are used to restore previous settings. – Shashwat Kumar Mar 05 '14 at 12:09
  • Ok, I hope that I have marked the answer as accepted now(I didn't know that there existed such a thing before :P) Thanks for the explanation! – Henrik Mar 05 '14 at 17:42
0

Most of Dos, Windows 3.x or win32 platform provide the file conio.h, but unix or linux Os is not provide this file normally. If you use unix or linux Os , you must download it on the internet By yourself. i hope my answer is useful for you.

luwenbin
  • 1
  • 1