C++ cin keypress event

31,499

Solution 1

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();
}

Solution 2

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;
}

Solution 3

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.

Share:
31,499
Lukas Salich
Author by

Lukas Salich

I like simple solutions, whenever possible. For me, correct design is the core for every development. If the design is poor, I enjoy refactoring of the code. I like working on a low level of abstraction, but let it stay virtual, because controlling the hardware manually can be too slow and boring for me. I am glad when I have the motivation to save a lot of means by proper design. I solve problems in contexts, so I do simple tasks more slowly than the others, but as a result, the time is usually saved in the end. Also, a lot of people think 2 steps ahead instead of questioning 1 step behind, I do the latter and it often leads to simpler solutions. I highly prefer C++11 onward (with ‘fixes’ from C++14 and filesystem/parallel algorithms from C++17), I like using RAII, range-based for loops, smart pointers, lambdas, optional, move semantics/rvalue references and similar wherever it’s useful, I quite like the thread support library although it’s fixed/updated every minor version, I use features from Boost when needed (uuid, multi_index, ..) and from time to time I check new features of the upcoming C++20 major version.

Updated on July 19, 2022

Comments

  • Lukas Salich
    Lukas Salich almost 2 years

    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.

  • Lukas Salich
    Lukas Salich almost 12 years
    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
    Lukas Salich almost 12 years
    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...
  • Bartek Banachewicz
    Bartek Banachewicz almost 12 years
    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
    Bartek Banachewicz almost 12 years
    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
    Bartek Banachewicz almost 12 years
    Nope, streams won't allow that. Look at my comment below my answer.
  • DevSolar
    DevSolar almost 12 years
    @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++.
  • Kiril Kirov
    Kiril Kirov almost 12 years
    This is for Windows only. It's not cross-platform (it's not written in the question, but reading the comments, you'll understand, that the question is for something standard.
  • huseyin tugrul buyukisik
    huseyin tugrul buyukisik almost 12 years
    Sorry, i didnt read the comments while i was building the answer ^^
  • Lukas Salich
    Lukas Salich almost 12 years
    So I can just use at the end of my loop: "if(kbhit()) break;"?
  • Software_Designer
    Software_Designer almost 12 years
    inside the while loop , add if(kbhit()) break;
  • Lukas Salich
    Lukas Salich almost 12 years
    Compiler can't find conio.h or just conio.
  • Lukas Salich
    Lukas Salich almost 12 years
    I can't even use the conio.h in compiler.
  • Lukas Salich
    Lukas Salich almost 12 years
    Isn't it old header? I use nearly newest G++ compiler btw.
  • Bartek Banachewicz
    Bartek Banachewicz almost 12 years
    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.
  • Tacet
    Tacet over 9 years
    conio.hms-dos, c header, so, so ugly!