Getch in combination with while-loop triggers loopcontent twice - c++

I'm not really a programmer so my knownledge is extremely limited, I'm just hoping to get a very basic program working for a project. I've been googling around a lot and from what I've found I'm guessing it has to do with getch reading blank spaces or new lines as an input or something along those lines. None of the solutions I have found seem to fix the issue for me however (I might be implementing them wrong though).
This is in the main function:
while (roundNum <= 20)
{
roundNum++;
cout << roundNum / 2 << endl;
arrowKey();
}
And the arrowKey function (which I found by googling so I don) looks like this:
int arrowKey()
{
int c = 0;
switch ((c = _getch()))
{
case KEY_UP:
cout << endl << "Up" << endl;
break;
case KEY_LEFT:
cout << endl << "Left" << endl;
break;
case KEY_RIGHT:
cout << endl << "Right" << endl;
break;
case KEY_DOWN:
cout << endl << "Down" << endl;
break;
}
return 0;
}
The problem is that the roundNum reads out twice as well as adds two to the number for every arrow key press, like this:
1
1
Up
2
2
Right
3
3
etc
Help is greatly appreciated!

The problem is that a char can only hold 255 values. Thus, in order to get more unique values getch sometimes uses two values to represent a key code, an instruction and a value. For example, try hitting the F keys and you'll notice the same issue arise.
Ultimately, the behavior you are experiencing is due to the fact that getch is being called twice for the arrow keys.
To fix this, check if the instruction is for the arrow keys, in this case the value is 224 for the arrows keys. Once you have identified an arrow keys is being pressed read in the second value with another call to getch and there you will be able to find the actual key.
#include <iostream>
#include <conio.h>
using namespace std;
enum KeyCodes {
KEY_UP = 72,
KEY_LEFT = 75,
KEY_RIGHT = 77,
KEY_DOWN = 80
};
int arrowKey()
{
int c = _getch();
if (c == 224) {
//another value
int key = _getch();
switch (key)
{
case KEY_UP:
cout << endl << "Up" << endl;
break;
case KEY_LEFT:
cout << endl << "Left" << endl;
break;
case KEY_RIGHT:
cout << endl << "Right" << endl;
break;
case KEY_DOWN:
cout << endl << "Down" << endl;
break;
}
}
return 0;
}
int main() {
int roundNum = 0;
while (roundNum <= 20)
{
roundNum++;
cout << roundNum / 2 << endl;
arrowKey();
}
}
It's also worth pointing out that getch is not apart of the std library and could thus have some variation.

Related

Arrow key Input without pausing console [duplicate]

I have been having a problem with detecting arrow key presses in my C++ console application. I have tried everything I have found, both here and on other tutorial sites, but all of them give me the same thing whenever I press the arrow:
Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.
Here are all the methods of detecting the key press that I have tried, all ending up the same way. These are the only two left in my code, the others I attempted I deleted instead of commenting out.
Method one:
c1 = getch();
if(c1 == 0)
{
c2 = getch();
if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
else{cout << endl << "Incorrect Input" << endl;}
}
Method two:
switch(getch()) {
case 65:
cout << endl << "Up" << endl;//key up
break;
case 66:
cout << endl << "Down" << endl; // key down
break;
case 67:
cout << endl << "Right" << endl; // key right
break;
case 68:
cout << endl << "Left" << endl; // key left
break;
}
Is there some error in my code which made me go back to my main method, or did it skip over some code? Is there a faster way to do this? I'm almost 100% sure that my other code doesn't have anything to do with this problem, because I isolated the code from be dependent on any other aspect of the program, and I kept having the same problem.
Again, I tried every method of getting the arrow key press that I could find, and I keep getting the same problem. If it matters, I'm on a Windows 8 Samsung ATIV Smart PC and using the keyboard dock.
Thanks in advance for any help.
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
int main()
{
int c = 0;
while(1)
{
c = 0;
switch((c=getch())) {
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << "null" << endl; // not arrow
break;
}
}
return 0;
}
output like this:
Up
Down
Right
Left
Up
Left
Right
Right
Up
detected arrow key press!
The previous answer by arbboter is close but neglects the fact the arrow keys (and other special keys) return a scan code of two characters. The first is either (0) or (224) indicating the key is an extended one; the second contains the scan code value.
Without accounting for this, the ASCII values for "H", "K", "M", and "P" are misinterpreted as "Up", "Down", "Left", and "Right".
Here's a modified version of arbboter's code to demonstrate reading the extended value when one of the arrow keys is pressed:
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_DOWN 80
int main()
{
int c, ex;
while(1)
{
c = getch();
if (c && c != 224)
{
cout << endl << "Not arrow: " << (char) c << endl;
}
else
{
switch(ex = getch())
{
case KEY_UP /* H */:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN /* K */:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT /* M */:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT: /* P */
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << (char) ex << endl; // not arrow
break;
}
}
}
return 0;
}
// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam#doctort.org> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri
#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
struct termios t;
tcgetattr(STDIN_FILENO, &t);
t.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t);
// Once the buffering is turned off, the rest is simple.
cout << "Enter a character: ";
char c,d,e;
cin >> c;
cin >> d;
cin >> e;
cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
if ((c==27)&&(d==91)) {
if (e==65) { cout << "UP";}
if (e==66) { cout << "DOWN";}
if (e==67) { cout << "RIGHT";}
if (e==68) { cout << "LEFT";}
}
return 0;
}
reference
Here is an alternate way to do it without getch() using events (well commented and i tried to make it as simple as i could)
#include <iostream>
#include <Windows.h>
int main(int argc, char *argv[]){
HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE); // handle to read console
DWORD Events = 0; // Event count
DWORD EventsRead = 0; // Events read from console
bool Running = true;
//programs main loop
while(Running) {
// gets the systems current "event" count
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events != 0){ // if something happened we will handle the events we want
// create event buffer the size of how many Events
INPUT_RECORD eventBuffer[Events];
// fills the event buffer with the events and saves count in EventsRead
ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);
// loop through the event buffer using the saved count
for(DWORD i = 0; i < EventsRead; ++i){
// check if event[i] is a key event && if so is a press not a release
if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){
// check if the key press was an arrow key
switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN: // if any arrow key was pressed break here
std::cout<< "arrow key pressed.\n";
break;
case VK_ESCAPE: // if escape key was pressed end program loop
std::cout<< "escape key pressed.\n";
Running = false;
break;
default: // no handled cases where pressed
std::cout<< "key not handled pressed.\n";
break;
}
}
} // end EventsRead loop
}
} // end program loop
return 0;
}
(Thanks to a commenter I now know this code is not standard, though it will work if you compile with g++, more info in the comments)
Some of the answers given here are not considering the fact that on pressing an arrow key, 2 characters are received. Additionally, it is to be noted that input character should be unsigned char. This is because to determine if an arrow key was pressed, we use ASCII value 224, which can only be stored in an 8-bit character (unsigned char) and not the 7-bit signed char.
You can use below code snippet. 2 types of inputs are processed here. ch1 is the 1st character that user enters. This is the input that user is feeding. But in case of arrow keys, a sequence of 2 characters are received ch1 and ch2. ch1 identifies that some arrow key was pressed, ch2 determines the specific arrow key pressed.
const int KEY_ARROW_CHAR1 = 224;
const int KEY_ARROW_UP = 72;
const int KEY_ARROW_DOWN = 80;
const int KEY_ARROW_LEFT = 75;
const int KEY_ARROW_RIGHT = 77;
unsigned char ch1 = _getch();
if (ch1 == KEY_ARROW_CHAR1)
{
// Some Arrow key was pressed, determine which?
unsigned char ch2 = _getch();
switch (ch2)
{
case KEY_ARROW_UP:
// code for arrow up
cout << "KEY_ARROW_UP" << endl;
break;
case KEY_ARROW_DOWN:
// code for arrow down
cout << "KEY_ARROW_DOWN" << endl;
break;
case KEY_ARROW_LEFT:
// code for arrow right
cout << "KEY_ARROW_LEFT" << endl;
break;
case KEY_ARROW_RIGHT:
// code for arrow left
cout << "KEY_ARROW_RIGHT" << endl;
break;
}
}
else
{
switch (ch1)
{
// Process other key presses if required.
}
}
Check http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
#include<windows.h>
#include <stdio.h>
int main()
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD NumInputs = 0;
DWORD InputsRead = 0;
bool running = true;
INPUT_RECORD irInput;
GetNumberOfConsoleInputEvents(hInput, &NumInputs);
ReadConsoleInput(hInput, &irInput, 1, &InputsRead);
switch(irInput.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
puts("Escape");
break;
case VK_LEFT:
puts("Left");
break;
case VK_UP:
puts("Up");
break;
case VK_RIGHT:
puts("Right");
break;
case VK_DOWN:
puts("Down");
break;
}
}
#include <iostream>
#include <conio.h>
const int KB_UP = 72;
const int KB_DOWN = 80;
const int KB_RIGHT = 77;
const int KB_LEFT = 75;
const int ESC = 27;
int main() {
while (true) {
int ch = _getch();
if (ch == 224) {
ch = _getch();
switch (ch) {
case KB_UP:
std::cout << "up\n";
break;
case KB_DOWN:
std::cout << "down\n";
break;
case KB_RIGHT:
std::cout << "right\n";
break;
case KB_LEFT:
std::cout << "left\n";
break;
default: std::cout << "unknown\n";
}
}
else if (ch == ESC)
{
std::cout << "Escape pressed, going out!\n";
break;
}
}
}
This is very simular to some example above except that I used
_getchar()
instead of
getchar()
that visual studio (which I use to write and run my cod)
gives error about,
and I also put it in a loop till you press Escape bottom.

Pressing certain key

I'm trying to learn C++, my first idea was to make simple win/lost ratio calculator, but it's not working well.
This is my code:
#include<iostream>
#include<conio.h>
using namespace std;
int match=0;
int win=0;
int lose=0;
int ratioo=1;
int total=0;
void lost()
{
if (match=='L');
lose=lose+1;
}
void won()
{
if (match=='W');
win=win+1;
}
int main() {
cout << "Welcome to winratio calculator!" << endl;
cout << "Pressing W adds one win point" << endl;
cout << "Pressing L adds one lose point" << endl;
cout << "Press ENTER to start" << endl;
cout << "Press ESC to close" << endl;
getch();
while(1)
{
cout << "Last game score: ";
cin >> match;
total++;
won();
lost();
ratioo=(win/total)*100;
cout << "Games won: " << win << endl;
cout << "Games lost: " << lose << endl;
cout << "Ratio: " << ratioo <<"%" << endl;
break;
}
return 0;
}
And now my problems:
1)After pressing ANY key there is +1 to win and lose same time
2)I got no idea how to start whole calculator with ENTER and stop it by ESC by getch();, tried few ways but always some errors on the way(it should add points all the time until ESC is pressed
Explanations are very welcome!
Okay, so it looks like we've got a couple of errors in your program as it is now. Let's take a look!
First thing's first. Notice that you have Semicolons at the end of your if statements.
void lost()
{
if (match=='L'); //NOTE: This is a useless if statement
lose=lose+1; //As is, this line will ALWAYS RUN regardless of what character is pressed.
}
void won()
{
if (match=='W'); //Same as Above ^^^^^
win=win+1;
}
Remember that in C, the if statement will execute the next statement conditionally. Remember also that a ; in C is a statement. So, by adding a semicolon after an if statement, you're nullifying the if conditional because the if statement will run the semicolon conditionally, and not your lose = lose + 1;.
Consider writing this instead:
void lost()
{
if (match == 'L')
{
lose = lose + 1;
}
}
void won()
{
if (match == 'W')
{
win = win + 1;
}
}
Furthermore, I noticed that you've inserted a break command to avoid an infinite while(1) loop. To avoid this problem. Consider using match = _getch() instead of cin << match.
match = _getch();
In addition, your Ratioo variable is not receiving anything but 0 due to truncation. To get the percentage you're looking for, you must cast your win/total to double as follows:
ratioo = ((double)win / (double)total) * 100;
So, Now we get to detecting the ESC And ENTER Keys! This is exciting. So, in order to read in these invisible characters, you have to understand that to the computer, these keys are just numbers. The ESC Key is number 27, and the ENTER Key is number 13 (Look Up the ASCII Table for a full list). So To detect them you need to do the following:
match = _getch();
if (match == 27) //27 is the ASCII Code for the Escape Key
{
break;
}
OR Just Substitute 13 if you're looking for the Enter key. By adding A while(1) Loop around it, you can pause a program until that key is pressed (AND ignore all other input).
My Final Version of your Code can be viewed below:
#include<iostream>
#include<conio.h>
using namespace std;
int match = 0;
int win = 0;
int lose = 0;
int ratioo = 1;
int total = 0;
void lost()
{
if (match == 'L')
{
lose = lose + 1;
}
}
void won()
{
if (match == 'W')
{
win = win + 1;
}
}
int main() {
cout << "Welcome to winratio calculator!" << endl;
cout << "Pressing W adds one win point" << endl;
cout << "Pressing L adds one lose point" << endl;
cout << "Press ENTER to start" << endl;
cout << "Press ESC to close" << endl;
while (1)
{
match = _getch();
if (match == 13) //13 is the ASCII Code for the Enter Key
{
break;
}
}
while (1)
{
cout << "Last game score: ";
match = _getch();
if (match == 27) //27 is the ASCII Code for the Escape Key
{
break;
}
total++;
won();
lost();
ratioo = ((double)win / (double)total) * 100;
cout << "Games won: " << win << endl;
cout << "Games lost: " << lose << endl;
cout << "Ratio: " << ratioo << "%" << endl;
}
return 0;
}
Enjoy! And I wish you well towards learning C!

Alternative to goto in nested loops?

This code is working fine, however this whole time I've tried avoiding using the goto statements that you will see in the switch (dice_total) statement.
Without the goto statements, the program will not loop back to the beginning of while (again=='y' || again=='Y'), and instead it keeps looping itself when it reaches the do-while loop.
However, I believe that it is also important to say, that if dice_total is = to the point_total the first time around then the program will function properly, and loop back to the beginning. For example, when the program starts, the first round will generate the point_total, which we will say its 10. Which is a value that will allow the program to continue to the next round, and if the dice_total also gets the same number, 10, the program will say you win, and the loop will work properly. However, if the program reaches the do while loop, and generates a number that isn't 10, but generates a 10 after a few loops, then the program will not loop to the beginning. So what I want to ask, what is wrong with my switch(dice_total) statement, and how can I fix it, to give the program the same effect without using the goto statements?
#include "stdafx.h"
#include <iostream>
#include <random>
#include <string>
using namespace std;
int main()
{
//Declared Variables***********************************
char again = 'y';
int point1;
int point2;
int point_total;
int round_1=1;
int dice1;
int dice2;
int dice_total;
//*****************************************************
//RANDOM SEED******************************************
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int>dist(1, 6);
//*****************************************************
start://TEMPORARY
while (again == 'y'||again=='Y')
{
int round_1 = 1;
system("CLS");
cout << "WELCOME TO THE CRAPS GAME" << endl;
cout << "THROWING ROUND:" << round_1 << " DICES.............." << endl;
point1 = dist(mt);
point2 = dist(mt);
point_total = point1 + point2;
cout << "ROUND: " << round_1 << " First dice is: " << point1 << " and second dice is: " << point2 <<" and the total is:"<<point_total<< endl;
switch (point_total)
{
case 7:
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
break;
case 2:
case 3:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
break;
default:
do
{
++round_1;
cout << "ROUND " << round_1 << endl;
dice1 = dist(mt);
dice2 = dist(mt);
dice_total = dice1 + dice2;
cout << "THROWING ROUND: " << round_1 << " DICES.............." << endl;
cout << "ROUND 1 DICE TOTAL IS: " << point_total << endl;
cout << "ROUND: " << round_1 << " First dice is: " << dice1 << " and second dice is: " << dice2 << " and the total is:" << dice_total << endl;
switch (dice_total)
{
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
goto start;
case 2:
case 3:
case 7:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
goto start;
default:
if (dice_total == point_total)
{
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!<<endl;
cin >> again;
break;
}//if
else
{
cout << "Going to next round" << endl;
}
}//dice_total
}//do
while (dice_total != point_total);
break;
}//switch point
}//again while
}//main
The problem you're facing is usual when you have too many nested loops in the same function, and is an indicator that you need to refactor parts of your code to be in their own functions.
If you do this, then you have more possibilities to control the flow of your code: in each function you have break and return, and as you can return a custom value, you can use it to determine in the surrounding function if you need to break or return again.
Besides, this gives you the opportunity to put self-explanatory names to your functions, which makes your code clearer for people that look at it for the first time (as it's written, it's so dense that I can't understand it unless I stare at it for some minutes).
An example of what I mean in code:
Before
int main() {
start:
while (a) {
b1();
switch(c) {
case 1:
do {
d();
if (cond) goto start;
} while(e);
break;
}
b2();
}
}
After
int main() {
while (a) {
if (!doStuff1())
break;
}
...
}
bool doStuff1() {
b1();
while (a) {
bool res = doStuff2();
if (res) return true;
}
b2();
...
}
bool doStuff2() {
switch(c) {
case 1:
if (doStuff3()) return true;
}
return false;
}
bool doStuff3() {
do {
d();
if (cond) return true;
} while (e);
return false;
}
How about this design?
bool stop=false;
while(!stop && (again == 'y'||again=='Y'))
{
while(again == 'y'||again=='Y')
{
// ...
break; /* breaks inner while*/
// ...
stop=true;
break; /* breaks inner while, and prevents running outer loop*/
}
}

C++ Detect when user presses arrow key

I have been having a problem with detecting arrow key presses in my C++ console application. I have tried everything I have found, both here and on other tutorial sites, but all of them give me the same thing whenever I press the arrow:
Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.
Here are all the methods of detecting the key press that I have tried, all ending up the same way. These are the only two left in my code, the others I attempted I deleted instead of commenting out.
Method one:
c1 = getch();
if(c1 == 0)
{
c2 = getch();
if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
else{cout << endl << "Incorrect Input" << endl;}
}
Method two:
switch(getch()) {
case 65:
cout << endl << "Up" << endl;//key up
break;
case 66:
cout << endl << "Down" << endl; // key down
break;
case 67:
cout << endl << "Right" << endl; // key right
break;
case 68:
cout << endl << "Left" << endl; // key left
break;
}
Is there some error in my code which made me go back to my main method, or did it skip over some code? Is there a faster way to do this? I'm almost 100% sure that my other code doesn't have anything to do with this problem, because I isolated the code from be dependent on any other aspect of the program, and I kept having the same problem.
Again, I tried every method of getting the arrow key press that I could find, and I keep getting the same problem. If it matters, I'm on a Windows 8 Samsung ATIV Smart PC and using the keyboard dock.
Thanks in advance for any help.
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
int main()
{
int c = 0;
while(1)
{
c = 0;
switch((c=getch())) {
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << "null" << endl; // not arrow
break;
}
}
return 0;
}
output like this:
Up
Down
Right
Left
Up
Left
Right
Right
Up
detected arrow key press!
The previous answer by arbboter is close but neglects the fact the arrow keys (and other special keys) return a scan code of two characters. The first is either (0) or (224) indicating the key is an extended one; the second contains the scan code value.
Without accounting for this, the ASCII values for "H", "K", "M", and "P" are misinterpreted as "Up", "Down", "Left", and "Right".
Here's a modified version of arbboter's code to demonstrate reading the extended value when one of the arrow keys is pressed:
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_DOWN 80
int main()
{
int c, ex;
while(1)
{
c = getch();
if (c && c != 224)
{
cout << endl << "Not arrow: " << (char) c << endl;
}
else
{
switch(ex = getch())
{
case KEY_UP /* H */:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN /* K */:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT /* M */:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT: /* P */
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << (char) ex << endl; // not arrow
break;
}
}
}
return 0;
}
// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam#doctort.org> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri
#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
struct termios t;
tcgetattr(STDIN_FILENO, &t);
t.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t);
// Once the buffering is turned off, the rest is simple.
cout << "Enter a character: ";
char c,d,e;
cin >> c;
cin >> d;
cin >> e;
cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
if ((c==27)&&(d==91)) {
if (e==65) { cout << "UP";}
if (e==66) { cout << "DOWN";}
if (e==67) { cout << "RIGHT";}
if (e==68) { cout << "LEFT";}
}
return 0;
}
reference
Here is an alternate way to do it without getch() using events (well commented and i tried to make it as simple as i could)
#include <iostream>
#include <Windows.h>
int main(int argc, char *argv[]){
HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE); // handle to read console
DWORD Events = 0; // Event count
DWORD EventsRead = 0; // Events read from console
bool Running = true;
//programs main loop
while(Running) {
// gets the systems current "event" count
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events != 0){ // if something happened we will handle the events we want
// create event buffer the size of how many Events
INPUT_RECORD eventBuffer[Events];
// fills the event buffer with the events and saves count in EventsRead
ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);
// loop through the event buffer using the saved count
for(DWORD i = 0; i < EventsRead; ++i){
// check if event[i] is a key event && if so is a press not a release
if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){
// check if the key press was an arrow key
switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN: // if any arrow key was pressed break here
std::cout<< "arrow key pressed.\n";
break;
case VK_ESCAPE: // if escape key was pressed end program loop
std::cout<< "escape key pressed.\n";
Running = false;
break;
default: // no handled cases where pressed
std::cout<< "key not handled pressed.\n";
break;
}
}
} // end EventsRead loop
}
} // end program loop
return 0;
}
(Thanks to a commenter I now know this code is not standard, though it will work if you compile with g++, more info in the comments)
Some of the answers given here are not considering the fact that on pressing an arrow key, 2 characters are received. Additionally, it is to be noted that input character should be unsigned char. This is because to determine if an arrow key was pressed, we use ASCII value 224, which can only be stored in an 8-bit character (unsigned char) and not the 7-bit signed char.
You can use below code snippet. 2 types of inputs are processed here. ch1 is the 1st character that user enters. This is the input that user is feeding. But in case of arrow keys, a sequence of 2 characters are received ch1 and ch2. ch1 identifies that some arrow key was pressed, ch2 determines the specific arrow key pressed.
const int KEY_ARROW_CHAR1 = 224;
const int KEY_ARROW_UP = 72;
const int KEY_ARROW_DOWN = 80;
const int KEY_ARROW_LEFT = 75;
const int KEY_ARROW_RIGHT = 77;
unsigned char ch1 = _getch();
if (ch1 == KEY_ARROW_CHAR1)
{
// Some Arrow key was pressed, determine which?
unsigned char ch2 = _getch();
switch (ch2)
{
case KEY_ARROW_UP:
// code for arrow up
cout << "KEY_ARROW_UP" << endl;
break;
case KEY_ARROW_DOWN:
// code for arrow down
cout << "KEY_ARROW_DOWN" << endl;
break;
case KEY_ARROW_LEFT:
// code for arrow right
cout << "KEY_ARROW_LEFT" << endl;
break;
case KEY_ARROW_RIGHT:
// code for arrow left
cout << "KEY_ARROW_RIGHT" << endl;
break;
}
}
else
{
switch (ch1)
{
// Process other key presses if required.
}
}
Check http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
#include<windows.h>
#include <stdio.h>
int main()
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD NumInputs = 0;
DWORD InputsRead = 0;
bool running = true;
INPUT_RECORD irInput;
GetNumberOfConsoleInputEvents(hInput, &NumInputs);
ReadConsoleInput(hInput, &irInput, 1, &InputsRead);
switch(irInput.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
puts("Escape");
break;
case VK_LEFT:
puts("Left");
break;
case VK_UP:
puts("Up");
break;
case VK_RIGHT:
puts("Right");
break;
case VK_DOWN:
puts("Down");
break;
}
}
#include <iostream>
#include <conio.h>
const int KB_UP = 72;
const int KB_DOWN = 80;
const int KB_RIGHT = 77;
const int KB_LEFT = 75;
const int ESC = 27;
int main() {
while (true) {
int ch = _getch();
if (ch == 224) {
ch = _getch();
switch (ch) {
case KB_UP:
std::cout << "up\n";
break;
case KB_DOWN:
std::cout << "down\n";
break;
case KB_RIGHT:
std::cout << "right\n";
break;
case KB_LEFT:
std::cout << "left\n";
break;
default: std::cout << "unknown\n";
}
}
else if (ch == ESC)
{
std::cout << "Escape pressed, going out!\n";
break;
}
}
}
This is very simular to some example above except that I used
_getchar()
instead of
getchar()
that visual studio (which I use to write and run my cod)
gives error about,
and I also put it in a loop till you press Escape bottom.

can I know which Keyboard Key has been pressed before hitting Enter

can I know which Keyboard Key has been pressed before hitting Enter.is there any way to capture such key pressed event in c++ ??Please provide a short example of it.
i'm using VC++ on Windows 32bit.
// See <url: http://en.wikipedia.org/wiki/Conio.h>.
#include <iostream>
#include <conio.h> // ! Non-standard, but de facto std. on Windows.
int main()
{
using namespace std;
for( ;; )
{
cout << "OK, should this program stop now..." << endl;
cout << "Press Y for Yes or N for No: " << flush;
for( bool answered = false; !answered; )
{
char const ch = getch(); // From [conio.h].
switch( ch )
{
case 'y':
case 'Y':
cout << "<- Yes" << endl; // Input echo.
cout << "Bye!" << endl;
return 0;
case 'n':
case 'N':
cout << "<- No" << endl; // Input echo.
cout << endl;
answered = true;
default:
;
}
}
}
}
For GUI programs is a bit different.
Note: you can also go all the way down to the Windows API if you want, but, I recommend taking one step at a time, exploring the conio.h functionality first.
Cheers & hth.,