7

I believe this is a very simple question, but I can't find a simple answer to it. I have an infinite loop, e.g. while(1), for(;;), and I need to break from the loop on a keypress. What is the easiest way to do this?

P.S.: I can't use getch, cin.ignore, or cin.get because it stops the loop.

Derek
  • 1,104
  • 13
  • 35
Lukas Salich
  • 959
  • 2
  • 12
  • 30
  • If you tell us more of the context, I'm pretty sure we could come up with something. Otherwise, you'll need to use some OS specific things. – Kiril Kirov Aug 16 '12 at 13:06
  • 1
    Some linux on server. I don't know, which distro. Isn't there a cross-platform solution in std? – Lukas Salich Aug 16 '12 at 13:15

4 Answers4

3

Well, what you want is asynchronous input. All of the methods provided by cin wait for enter. You will have to use system-specific functions for that, or use a library that will do it for you.

What you need to do is to not only process your logic in a while loop, but also listen from message pipe from your OS. If you want some more information about that one, please drop a comment.

EDIT: There's one other way, but I wouldn't recommend it as it can be non-portable I believe. The following code compiles and runs under VS2012RC.

#include<iostream>
#include<conio.h>

using namespace std;

int main()
{
   cout << "Enter a character";
   getch();
}
Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • 1
    Wow, I thought that something so simple as keypress will be implemented in a same way on all platforms. I understand that cin is just some stream, but I still think that there will be a crossplatform solution. I will be running it on a server where is some linux, but I don't know which distro. I also remember, when long time ago I tried something in Pascal at school, there was just an event "keypressed" so I simply written "repeat until keypressed;" so in C++ while(?) {}? – Lukas Salich Aug 16 '12 at 13:08
  • Well, message processing on linux is fairly simple, I believe. You just have to run one or two OS calls to poll for a message and then to run default action if you don't want to do anything. The essential difference is that with streams, you get `char` of character entered, whilst using OS calls you get Key Up/Down events, you can use modifier keys as "normal ones" (shift, ctrl, etc.) – Bartek Banachewicz Aug 16 '12 at 13:13
  • As to the "Pascal" question, look at the `conio.h`/`getch()` function. It can me named differently based on the compiler you are using, but actually it's usually provided. (It can be `getch`, `getchar` or whatever) – Bartek Banachewicz Aug 16 '12 at 13:14
  • I can't even use the conio.h in compiler. – Lukas Salich Aug 16 '12 at 14:52
  • Isn't it old header? I use nearly newest G++ compiler btw. – Lukas Salich Aug 16 '12 at 17:35
  • I warned you about portability issues. You will have to do it "the proper way". I suggest using ready-made library. Google for "simple linux message library" or something like that. – Bartek Banachewicz Aug 16 '12 at 20:03
  • [conio.h](https://en.wikipedia.org/wiki/Conio.h) — [tag:MS-DOS], [tag:C] header, so, so ugly! – Tacet Nov 22 '14 at 23:38
3

Below is a Windows console code that uses kbhit() and has an infinite loop. But if keyboard is hit, it breaks the loop and exits. If you have <conio.h> , try this :

#include <iostream> 
#include <conio.h>

using namespace std;


int main()
{


   while (1)
   { 
     if (kbhit()) break;

   }

  return 0;
}
Software_Designer
  • 8,490
  • 3
  • 24
  • 28
2

There is no "keyboard" in C++. You only have an opaque input data stream which your terminal popu­lates occasionally with its own keyboard input. This is almost always a buffered, editable line-wise input, so you have no way of knowing when any given key was pressed.

You need a platform-specific method to communicate directly with your terminal on a lower level. One such library, fairly wide-spread and portable, is ncurses (a compatible Windows variant exists). Portable graphical application frameworks such as SDL and Allegro also provide raw keyboard handling.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Omg, there must be a simple solution in std. For example in every itteration of the loop get data from that input data stream (cin?) and check, if it is empty, but I don't know, how to do it... – Lukas Salich Aug 16 '12 at 13:13
  • Nope, streams won't allow that. Look at my comment below my answer. – Bartek Banachewicz Aug 16 '12 at 13:15
  • @LukasSalich: Look at it this way: If your C++ application would receive every keypress event, it would be *responsible* for it. Your C++ program would have to handle the line editing, for example, which in turn would require intimate knowledge of the terminal API so you can e.g. delete a character on pressing backspace. To safe the average C++ app/runtime of this burden, this is not part of the standard. There are, however, many libraries that do this, like conio, ncurses, etc.; this means you can chose whatever library *best* suits your needs. One of the big fat plusses of C/C++. – DevSolar Aug 16 '12 at 13:20
0

This checks if "left arrow" is being pressed or not:

GetKeyState(VK_LEFT)

Also this does not wait for anything. Just checks some flags.

Some other keys defined in winuser.h:

#define VK_NUMPAD0        0x60
#define VK_NUMPAD1        0x61
#define VK_NUMPAD2        0x62
#define VK_NUMPAD3        0x63
#define VK_NUMPAD4        0x64
#define VK_NUMPAD5        0x65
#define VK_NUMPAD6        0x66
#define VK_NUMPAD7        0x67
#define VK_NUMPAD8        0x68
#define VK_NUMPAD9        0x69

#define VK_CLEAR          0x0C
#define VK_RETURN         0x0D

#define VK_SHIFT          0x10
#define VK_CONTROL        0x11
#define VK_MENU           0x12
#define VK_PAUSE          0x13
#define VK_CAPITAL        0x14

#define VK_KANA           0x15
#define VK_HANGEUL        0x15  /* old name - should be here for compatibility */
#define VK_HANGUL         0x15
#define VK_JUNJA          0x17
#define VK_FINAL          0x18
#define VK_HANJA          0x19
#define VK_KANJI          0x19

#define VK_ESCAPE         0x1B

#define VK_CONVERT        0x1C
#define VK_NONCONVERT     0x1D
#define VK_ACCEPT         0x1E
#define VK_MODECHANGE     0x1F

#define VK_SPACE          0x20
#define VK_PRIOR          0x21
#define VK_NEXT           0x22
#define VK_END            0x23
#define VK_HOME           0x24
#define VK_LEFT           0x25
#define VK_UP             0x26
#define VK_RIGHT          0x27
#define VK_DOWN           0x28
#define VK_SELECT         0x29
#define VK_PRINT          0x2A
#define VK_EXECUTE        0x2B
#define VK_SNAPSHOT       0x2C
#define VK_INSERT         0x2D
#define VK_DELETE         0x2E
#define VK_HELP           0x2F

winuser.h must be included in windows.h

huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97