how to detect arrow keys - c++

I have created an application for detect pressing up and down key on keyboard
but nothing will be printed after pressing these keys.
I am using Visual C++ 2010
#include <iostream>
#include <conio.h>
using namespace std;
void main()
{
char x;
while(1)
{
x = getch();
if(x==0 || x==224)
{
x=getch();
if(x==80)
{
cout << "down"<<endl;
}
else if(x==72)
{
cout << "up"<<endl;
}
}//if x==0 || x=224
}//while1
}//main
What can be the problem?
Thanks

Just to answer why it isn't working: You are trying to use your user's input as unsigned. Your character variable is signed so the value is different than you are expecting. An unsigned 224 is a signed -32.
As far as your loop goes I'd suggest changing things to this.
void main()
{
char x;
while(true)
{
while(!kbhit()){}
x = getch();
if(x==0 || x==-32)
{
x=getch();
if(x==80)
{
cout << "down"<<endl;
}
else if(x==72)
{
cout << "up"<<endl;
}
}//if x==0 || x=224
}//while1
}//main
The program will still loop forever. Then the next loop, which I added, will continue to loop while there are no keys being pressed(buffered). Then getch() grabs the next char from the buffer. Now the problem you were running into, is that you had 224 (0xE0) which is technically correct. However in binary apparently -32 and 224 look the same.
I ran into a bit of the same issue at first, I couldn't figure out why my code wasn't hitting the correct code block and it was because the first character was actually -32 (0xE0)
Hope that is of some help, despite this being a really old question.

You can use the curses.h library. Read their guide and it should be very easy from there.
After you take input using getch() (store the input into an int, not a char), you can verify if it's one of the arrow keys using the defined keycodes. Just make sure you used keypad(stdscr, TRUE) before for the program to be able to recognize the arrow keys.

Us kbhit() to get Keyboard Arrow Keys

Related

Why does _getch() still wait for enter instead of directly registering the user input?

I would like to use arrow keys user input without the user having to press enter every time after clicking the arrow. Therefore, I decided to use _getch(), which allegedly does exactly that. It is part of the conio.h library, which I imported. However, in my case,_getch() also requires the user to press enter and doesn't immediately register the user input, as it should've. How can I fix that? (I'm running on windows)
#include<iostream>
#include <conio.h>
using namespace std;
int main() {
int p = _getch();
cout<<p;
return 0;
}
For example, in the code above instead of directly printing the value of p after receiving input in the console, it still waits for enter to be pressed.
From Microsoft Docs:
When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.
So a revised version of your code might look like this:
#include <iostream>
#include <conio.h>
int main() {
int p = 0;
while(p == 0 || p == 0xE0)
p = _getch();
std::cout << p;
return 0;
}

Why doesn't my code work in visual studio?

this is my code
#include <conio.h>
#include <iostream>
using namespace std;
int main() {
bool a = false;
char b='p';
int c=0;
while (a != true) {
if (_kbhit()) {
b = _getch();
}
if (b=='w') {
c++;
cout << c << " ";
}
else if (b == 'c') {
cout << "hello";
}
}
system("pause");
return 0;
}
The problem is where when I press 'w' I want it to print out the value of c and it should be repeating until i press another input for _kbhit() right? because now it add 1 to c then prints c and when i press w again samething. What's wrong with my visual studio I'm using community 2017 I've tried to uninstall it and install it again but same problem occurs.
The problem you're running into seems to be a result of a recently added bug in _getch()/_kbhit.
For an extended key (e.g., a cursor key) it's documented that _getch() returns either a 0x0 or 0xe0 followed by the scan code for the key that was actually pressed. What's not documented is that if the user presses a non-extended key, _kbhit will still return true twice in succession, and calls to _getch() will return the key code the first time, and 0x0 the second time.
In your code, when the user presses 'w' or 'c', _kbhit will return true not just once (as you'd expect) but twice. The first time you call it, it'll return the scan code of the key, and the second it'll return a 0 byte.
What's happening in your code is that you're reading the scan code, printing something appropriately, then _kbhit is returning true again, so you read the '\0' byte, set b to '\0', and then (since you don't have any code to do anything when b is 0) you (repeatedly) do nothing until the next time the user presses a key.
Reference
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getch-getwch?view=vs-2017
It seems like the program behaves the way you want it to. If I press 'w', it goes into an infinite loop of increasing the value of c and printing it. Pressing any other key stops printing and pressing 'c' goes on the same infinite loop and prints hello. Doesn't seem to be any problems as far as the posted code is concerned. Also, I would like to say the same as #Someprogrammerdude, if it compiles, but doesn't behave the way you want it to, it's an issue with the code, not the IDE and/or compiler.
Hypothetical answer: Your computer might always be thinking that a key is pressed, thus kbhit() always returns true. This maybe caused by a bad mouse/keyboard/controller driver and/or configuration. The code is fine, your PC is not.

getch() reads two characters from one arrow key press

Today i was testing how key pressing might work in C++ and made simple loop for it,and found that getch() duplicate itself for some reason or idk what is going on honestly,just look at that:
#include <iostream>
#include <windows.h>
#include <conio.h>
#define VK_H 0x48
using namespace std;
int main()
{
int n=1;
int total=0;
bool theEnd=true;
while(theEnd)
{
cout<<total<<endl;
getch();
if(GetAsyncKeyState(VK_LEFT))
{
total -=n;
}else if(GetAsyncKeyState(VK_RIGHT))
{
total +=n;
}else if(GetAsyncKeyState(VK_LSHIFT) && GetAsyncKeyState(VK_F1))
{
total = 0;
} else if(GetAsyncKeyState(VK_ESCAPE))
{
break;
}
}
cout<<total<<endl;
}
Its pretty simple.Program starts with a loop,where endlessly outputs value of variable "total",and after pressing left/right buttons "total" decrements/increments by 1.
Its was worked fine and perfect when i was using system("pause"); Sleep(milliseconds); cin.get();(but this one assume pressing enter each time,so it is not proper one) ,all that output right value on the screen after each pressing on the buttons.But in case with getch(); it somehow appear to working like only one time per/two cycles of the loop.
So the result i've get is like this: i'm pressing button right - current loop working fine,but next one working like without getch(),incrementing and outputting one more time without my command...
I've siting and thinking couple hours,trying find any answers in google and here but nothing...
P.S.without using getch() or other things for purpose stoping loop till next pressing - it will add not +1 to total by single pressing(as i need),but hundreds(average pressing key will do 150-300 loops lol).
From MS documentation
Remarks
The _getch and_getwch functions read a single character from the
console without echoing the character. None of these functions can be
used to read CTRL+C. When reading a function key or an arrow key, each
function must be called twice; the first call returns 0 or 0xE0, and
the second call returns the actual key code.
When you press arrow keys, the input is 2 chars

Reading a combination without confirming with enter?

So basically I just want to read characters from the user and make my code know that when user types a defined combination (say, CTRL+F - but without confirming with Enter, for exmaple), it's the end of the input. How can I do that? I only know how to read characters with enter and comparing their ASCII's...
EDIT
Reading through your question again, I realize that I misinterpreted your question. I'll leave this since it might still be useful to you or others.
What you're asking for doesn't have to do much with reading characters. In fact, CTRL is not a character at all. You're basically just checking for key pushes. Handling this kind of input is platform dependent, and even on a single platform, multiple methods will exist. One way to do it for windows is by using GetAsyncKeyState. This function will check whether a specified key is being pushed right now. Note that it doesn't 'remember' input, so you'll have to check this function many times per second to register all user input.
You supply the function with a single argument specifying the key of which you want to check the state. A list of all key codes can be found here
Example:
#include <iostream> //for output
#include <windows.h> //for GetAsyncKeyState
int main()
{
while(true)
{
if( GetAsyncKeyState(VK_CONTROL) ) //CTRL-key is pressed
{
if( GetAsyncKeyState( 0x46 ) ) //F-key is pressed
std::cout << "CTRL-F is pressed" << std::endl;
if( GetAsyncKeyState( 0x58 ) ) //X-key is pressed
break;
}
}
std::cout << "CTRL-X was pressed, stopping.." << std::endl;
}
This example will continuously check if CTRL-F is being pushed and if so write output, until CTRL-X is pressed.
The Windows system call ReadConsoleInput allows you to read console input directly. You may want to wrap that call into a function that just extracts the essential data from the several parameters of the ReadConsoleInput function. You can write a function to check if there is any input using GetNumberOfConsoleInputEvents.
try
#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
bool keepGoing = true;
char key = ' ';
while (keepGoing){
cout << "Enter a key" << endl;
while(_kbhit()){
key = _getch();
cout << "You entered: " << key << endl;
}
}
}
then specify delimiter when to end loop.
if on linux curses are available. there is also a getch function. you should use curses if you aim for cross platform compatibility. ncurses library functions are similar to ones in conio.h.
ncurses tutorial

C++ - Quitting a program

In the C++ Without Fear: A Beginner's Guide That Makes You Feel Smart book in chapter(8), part of a code trying to display a text file is the following:
while(1)
{
for(int i=1; i <= 24 && !file_in.eof(); i++)
{
file_in.getline(input_line,80);
std::cout<<input_line<<std::endl;
}
if(file_in.eof())
{
break;
}
std::cout<<"More? (Press 'Q' and ENTER to quit.)";
std::cin.getline(input_line,80);
c=input_line[0]; // <<<<<<
if(c=='Q'||c=='q')
{
break;
}
}
The part I'm not getting here is:
c=input_line[0];
I think it is put to read 'Q' or 'q'. But, why using this form (Array)? And, isn't there a way to read 'Q' or 'q' directly?
I tried std::cin>>c; but seemed to be incorrect.
Any ideas?
Thanks.
Because input_line is string ( array from chars), so input_line[0] gets the first letter - this is in case, that the user write "quit" or "Quit", not just "Q"
std::cin >> c; would be correct, if you enter just one char and press Enter
I tried std::cin>>c; but seemed to be incorrect.
That's correct, if c is a char.
You're right; reading an entire line just to extract a single character is bizarre. I recommend a book from this list.
You are getting the first character from the "array" into which the input line has been written.
NON-STANDARD solution, but works on windows platforms.
you can use getch() function defined in conio.h
example:
#include <conio.h>
...
char c = getch();
bye