My program starts by entering any key,then the user sees a color changing text "Welcome to my
program". Now, the user should hit any key to continue, but he can't quit the infinite loop that is changing the color of text. Let me show you the code for a better understanding.
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar();
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
}
This would be a solution for you (comments included)
#include <iostream>
#include <Windows.h>
#include <thread>
int main()
{
HANDLE color = GetStdHandle( STD_OUTPUT_HANDLE );
std::cout << "Press any key to start...";
bool stop = false; // use a Boolean instead of int
// doesn't really matter what the input is, so use getchar().
// Note, this is really just "enter". You can modify if you expect user to
// hit multiple keys before hitting enter
getchar();
// This line here will start a new thread which will wait for the user to hit enter
std::thread getInput = std::thread( [&stop] { getchar(); stop = true; } );
// Loop stays the same (except I inverse the "stop" variable to make more sense)
while ( !stop ) {
for ( int i = 10; i <= 15; i++ ) {
std::cout << ( "\n\t\t\t\t\t Welcome to my program\n" );
SetConsoleTextAttribute( color, i );
Sleep( 100 );
system( "cls" );
}
}
}
When you are using getchar() to get input from the user, it will store inside the integer stop the decimal value of the buffer the user entered.
For example: if the user entered '0', the stop variable will store the value 48 (the decimal value of the char '0').
And you while loop will keep running while stop is not equal to 0, which is never because the decimal value of all of the characters is not 0, the only character that its decimal value is 0 is NULL.
To fix your problem you will need to add an exit option according to your needs.
If you create a loop as follows:
int myInt = 1;
while (myInt)
{
std::cin >> myInt;
}
The loop will continue until the user enters 0. This is because conditional statements use 0 as "false" and in this case, any other value as "true".
The problem with your implementation is you only get the users input once, and even if the user enters "0" (in char format) the integer value associated is 48.
You could add this:
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar();
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
std::cin >> stop;
}
Now the loop will start when the user presses any key, then the the inner loop will run, then the user will need to enter a key again. If the user enters "0" this time the while() loop will break and the program will proceed.
If you are trying to keep a loop running while searching for user input to break the loop, then you are attempting a much more complex task. Look into the std::thread library if you are interested in this.
The issue with your code from what I could tell is that you're only initializing the variable "stop" once in your code and never inside your loop. So, the program will only ask the user for input once. A simple fix would be to continuously ask the user for input at the end of your for loop:std::cin>>stop;. In addition, like what others have already said, if the user inputs '0', it would implicitly typecast the char variable into an integer variable using ASCII. Since '0' corresponds to the integer value of 48, it would save 48 into the variable instead of 0. You can fix this by using this code:
HANDLE color=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"Press any key to start...";
int stop=getchar()-'0';
while(stop){
for(i=10;i<=15;i++){
cout <<("\n\t\t\t\t\t Welcome to my program\n");
SetConsoleTextAttribute(color,i);
Sleep(100);
system("cls");
}
std::cin>>stop;
}
Related
How to display what key was pressed?
I mean, like if you press A, on screen will display: You pressed A.
cin>>keypress;
cout<<"You pressed:"<<keypress;
I want to show directly what key I am pressing. Without waiting to press enter and finishing the execution.
I have a Windows only solution using the windows api.
#include <wInDoWs.h>.
you can use GetAsyncKeyState() and pass the ASCII value for the key to it. It will return a short indicating the status of the button. To the best of my knowledge, the value -32767 is returned when the button is pressed. Wrap that in a function and you can tell if the button is pressed. (below will run with copy/paste.)
#include <windows.h>
#include <iostream>
bool pressed(const short& _key)
{
short state = 0;
short pressed= -32767;
state = GetAsyncKeyState( _key);
return ( state == pressed );
}
int main()
{
//see if J is pressed
while(1)
{
if(pressed( 0x4a ) )// 'J'
std::cout << "J";
}
}
To make that work with all characters, I'm afraid I can't think of an easier way than storing all the ASCII values, and what you want to print out if the key is pressed, in a container and checking their pressed status every frame.(below is just pseudo code.)
//the container this short is the 'key'
std::vector< std::pair< short , std::string > > chars;
//to check the status
for(auto& c : chars)
if( pressed( c.first ) ) std::cout << c.second;
I would put that in some sort of loop.
Adding the 'you pressed space' wouldn't be difficult this way.
just do
chars.push_back( std::pair<int,std::string>(0x20 , "Spacebar") );
I think you want to display the character what are you pressing (like in your example). So, it's pretty simple. Here's the code:
#include <stdio.h>
#include <conio.h>
int main()
{
char keyPress;
while(1)
{
keyPress=_getch();
if((keyPress==27)||(keyPress==32))
{
printf("You decided to stop the execution of this code.");
return 0;
}
printf("You pressed:%c\n",keyPress);
}
}
If you let the code how it is, the program will finish the execution on esc or space pressed. If you want to change this, you can replace the numbers in: if((keyPress==27)||(keyPress==32)) with anothers ascii codes of your button. Here's all the ascii codes: https://ascii.cl/ . If you want to end the program only on one button, just modify from if((keyPress==27)||(keyPress==32)) into if(keyPress==27) and now the program will stop only on ESC.
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
I need to end my function once the user inputs CTRL-X or '/'. I don't know how to detect/check for a user input of CTRL-X.
The task given to me states:
'When you edit the file, you will enter data line by line and when done, you will enter ‘/’ or CTRL + X to exit.'
I have written this code so far. I'm a beginner so pardon my code.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string data;
int line_num=1;
ofstream editFile;
editFile.open("edit_test.txt");
while(data!="/"){ //some kind of condition ORed with the condition already present in while loop?
cout<<line_num<<"> "; //I want to display line numbers every time the user presses enter
getline(cin, data);
if(data!="/"){
editFile<<data<<endl;
line_num++;
}
}
editFile.close();
return 0;
}
CTRL+X is the same as character code 24 (since X is the 24th letter of the alphabet). Barring any system interference*, all you need to do is check to see if character code 24 is in the input.
while (getline( std::cin, s ))
{
// Find ^C in s
auto n = s.find( '\x18' );
if (n != s.npos) s = s.substr( 0, n );
// process s normally here
// If ^C was found in s, we're done reading input from user
if (n != s.npos) break;
}
CTRL+X doesn’t tend to have any special system actions attached to it, so you shouldn’t have any problem getting it as input.
Simple code to understand the problem:
string op;
int main()
{
cout<<"hi";
op=getch(); // or cin>>op
delay(2000) // delay for 2 sec.
cout<<endl<<" bye";
op=getch(); // or cin>>op
system("cls");
cout<<" MAGIc !! !!";
return 0;
}
What this code should be doing is:
Print "hi"
Wait for the user to press any key
Wait for two seconds
Print "bye"
Wait for the user to press any key again
Clear the screen
Print "Magic"
Let's say there are two users: User A and User B.
Let's say User A presses the 'a' key and then waits for two seconds until "bye" is displayed, and then presses 'a' again and then sees the screen clear and "magic" get printed. Well User A is good, and there is no problem.
But let's User B is impatient. User B sees "hi" and immediately presses 'a' twice. Then after two seconds, he only sees the word "Magic". He never sees "bye" because the screen is cleared right away!
So the question is: how do I prevent the second getch() from getting input if an impatient user presses too many keys before "bye" is printed, so that they have to press another key after "bye" is printed and before the screen is cleared?
sorry for being too late. in your case use: FlushConsoleInputBuffer to clear getch buffer:
int main()
{
cout<<"hi";
op=getch();
Delay(2000);
cout<<endl<<" bye";
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); // flushing the buffer
op=getch(); // or cin>>op
system("cls");
cout<<" MAGIc !! !!";
return 0;
}
user above can enter even 4 times a and everything will be alright.
it's so stupid to clear cin's buffer without using it
Suppose we have a menu which presents the user with some options:
Welcome:
1) Do something
2) Do something else
3) Do something cool
4) Quit
The user can press 1 - 4 and then the enter key. The program performs this operation and then presents the menu back to the user. An invalid option should just display the menu again.
I have the following main() method:
int main()
{
while (true)
switch (menu())
{
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
case 3:
doSomethingCool();
break;
case 4:
return 0;
default:
continue;
}
}
and the follwing menu():
int menu()
{
cout << "Welcome:" << endl
<< "1: Do something" << endl
<< "2: Do something else" << endl
<< "3: Do something cool" << endl
<< "4: Quit" << endl;
int result = 0;
scanf("%d", &result);
return result;
}
Entering numerical types works great. Entering 1 - 4 causes the program to perform the desired action, and afterwards the menu is displayed again. Entering a number outside this range such as -1 or 12 will display the menu again as expected.
However, entering something like 'q' will simply cause the menu to display over and over again infinitely, without even stopping to get the user input.
I don't understand how this could possibly be happening. Clearly, menu() is being called as the menu is displayed over and over again, however scanf() is part of menu(), so I don't understand how the program gets into this error state where the user is not prompted for their input.
I originally had cin >> result which did exactly the same thing.
Edit: There appears to be a related question, however the original source code has disappeared from pastebin and one of the answers links to an article which apparently once explained why this is happening, but is now a dead link. Maybe someone can reply with why this is happening rather than linking? :)
Edit: Using this example, here is how I solved the problem:
int getNumericalInput()
{
string input = "";
int result;
while (true)
{
getline(cin, input);
stringstream sStr(input);
if (sStr >> result)
return result;
cout << "Invalid Input. Try again: ";
}
}
and I simply replaced
int result = 0;
scanf("%d", &result);
with
int result = getNumericalInput();
When you try to convert the non-numeric input to a number, it fails and (the important part) leaves that data in the input buffer, so the next time you try to read an int, it's still there waiting, and fails again -- and again, and again, forever.
There are two basic ways to avoid this. The one I prefer is to read a string of data, then convert from that to a number and take the appropriate action. Typically you'll use std::getline to read all the data up to the new-line, and then attempt to convert it. Since it will read whatever data is waiting, you'll never get junk "stuck" in the input.
The alternative is (especially if a conversion fails) to use std::ignore to read data from the input up to (typically) the next new-line.
1) Say this to yourself 1000 times, or until you fall asleep:
I will never ever ever use I/O functions without checking the return value.
2) Repeat the above 50 times.
3) Re-read your code: Are you checking the result of scanf? What happens when scanf cannot convert the input into the desired format? How would you go about learning such information if you didn't know it? (Four letters come to mind.)
I would also question why you'd use scanf rather than the more appropriate iostreams operation, but that would suffer from exactly the same problem.
You need to verify if the read succeeded. Hint: it did not. Always test after reading that you successfully read the input:
if (std::cin >> result) { ... }
if (scanf("%d", result) == 1) { ... }
In C++ the failed state is sticky and stays around until it gets clear()ed. As long as the stream is in failed state it won't do anything useful. In either case, you want to ignore() the bad character or fgetc() it. Note, that failure may be due to having reached the end of the stream in which case eof() is set or EOF is returned for iostream or stdio, respectively.