5

If I want to loop until a keystroke there is a quite nice Windows solution:

while(!kbhit()){ 
    //...
}

But this is neither an ISO-Function nor works on other Operating Systems except MS Win. I found other cross-plattform solutions but they are quite confusing and bloated - isn't there another easy way to manage this?

NaN
  • 3,501
  • 8
  • 44
  • 77

2 Answers2

3

No, C++ standard doesn't define concepts like 'keyboard' and 'keystrokes', because not all systems have such things. Use a portable library, maybe ncurses should have something.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • 1
    Of course this is better way to use *ncurses*. Make inquiries for support by different OSes. – sergzach Aug 18 '11 at 10:16
  • 1
    In my experience, using "portable libraries" leads you into a dark rabbit hole. Usually they are badly written in the sense, that they try to make all OS look like the authors favorite/best known OS. With the result that at best they only produce something optimal just for that one OS the author favors. Instead, Write an abstraction (a header with a function prototype). And for N target systems, write N .c/c++ files, implementing that function in an optimal way. Then, just link to the respective implementation. – BitTickler Dec 03 '19 at 12:15
  • @BitTickler: that's what I usually do, but then I end up with yet another portable library to do X... :D – Yakov Galka Dec 03 '19 at 16:42
2

You can use the next version of kbhit() for *nix OSes:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#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;
}
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
sergzach
  • 6,578
  • 7
  • 46
  • 84
  • Please see the next for details: http://cboard.cprogramming.com/c-programming/63166-kbhit-linux.html – sergzach Aug 18 '11 at 10:11
  • Ok, this works, but this is not a *light* version and is far longer than the original kbhit()... but thanks - sounds like the best solution so far. – NaN Aug 18 '11 at 19:04
  • 1
    You could try to optimize it... But it is better to use cross-platform decisions. So don't use kbhit() if you are perfictionist. – sergzach Aug 19 '11 at 10:40