I am trying to implement a pause function in C++, but it is looping forever.
I am using macOS but I am trying to create a pause function that will work in any system... I believe my cin >> is not capturing '\n' or '\r' from the keyboard and it is looping forever.
void Transferencia::pause() {
char enter = 0;
while(enter != '\n' && enter != '\r') {
cout << "(Press Enter to Continue...) ";
cin >> enter;
}
cin.clear();
}
I want to pause my program until user press the key "enter".
But even when I press "enter/return" it keeps looping...
At very first: enter != '\n' || enter != '\r' is a tautology: Even if enter does equal one of the characters it cannot be equal to the other one. So one of the tests must be true... You actually want to stay in the loop when enter is unequal to both values.
std::cin >> ... won't read data before you press enter, but it will discard the newlines (actually, all whitespace). So it would suffice just to read one single character right without loop (the loop again would get an endless one); solely: If the user doesn't enter anything at all before pressing 'enter' key, there's no character to read from std::cin and we'd still be waiting.
What you can do is reading entire lines:
std::string s;
std::getline(std::cin, s);
That will accept empty lines as well, so does exactly what you want (note: no loop around!).
Edit (stolen from the comments; thanks, Thomas Matthews): An even more elegant way is
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
as it won't create any additional resources that would be discarded afterwards anyway (the std::string object!).
Edit 2:
Depending on type of last input operation, there might still be a newline (or even further data) buffered, e. g. after int n; std::cin >> n;. In this case, you need to skip the input yet buffered. So you would need ignore twice.
However, if the last input operation consumed the newline already (e. g. std::getline – or if there wasn't any preceding input operation at all), then this would lead to user having to press enter twice. So you need to detect what's has been going on before.
std::cin.rdbuf().in_avail() allows you to detect how many characters are yet buffered. So you can have:
if(std::cin.rdbuf().in_avail())
{
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout << "press enter" << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
On some systems (including mine), though, in_avail can return 0 even though a newline is yet buffered! std::cin.sync_with_stdio(false); can fix the issue; you should execute it before very first input operation. Hopefully, you don't use C++ (streams) and C (scanf, printf, etc) IO intermixed then...
The easiest way to do this is with getline().
cin >> ignores whitespace, newline characters included. getline() will read an entire line, newline character included. However, it does not copy the newline character to the output string. If the user simply hit the enter key and nothing else, you'd end up with an empty string.
So, to get your desired behavior, you would construct your loop like this:
string line;
while(true)
{
cout << "(Press Enter to Continue...) " << endl;
getline(cin, line);
if(line == "")
break;
}
#Aconcagua has answered your question but this is what I want to add in.
Normally, for handling some specific kind of event in computer, we usually follow event-driven paradigm or event-callback.
The idea is there is an event loop that waits for a new event coming into the system. This case, keyboard is an event, the event loop then calls event-callback. What event-callback does is it compares the value of input with some conditions then do some other tasks (it might change some state of the program or notify users).
The idea is keep CPU busy by either 2 ways.
event-driven : do other tasks while waiting for a new event
multithreading: multiple threads in the system. This approach has the disadvantage is at data-race
Have fun
Related
Here's the scaled down version of the program which accepts an unknown no. of Integer inputs. I used cin.get() before but to no avail, finally used this but unfortunately it too didn't worked. I am using Notepad++ spawning command prompt to run my programs. Is this something to do with Notepad++ OR the CTRL-Z (end-of-file) character?
EDIT : Works fine using cmd.exe
vector<int> vint;
int val = 0;
cout << "Enter integers..... Press CTRL and \'Z\' when done entering!"
<< "\n GO... : ";
while(cin >> val)
vint.push_back(val);
if (vint.size() > 1)
{
...
}
else
{
...
}
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n' );
std::cin.get();
When you enter Ctrl+Z in a console programme you tell that it's the end of the file. Any subsequent reading from cin is then doomed to fail.
It works from the command line, because the command processor doesn't close the window when the programme is over.
Possible solutions:
The portable approach would be to interupt the loop cleanly by checking for a special value (for example 0).
If this is not possible, another approach would be to gain more control on the user input and read lines into a string. You could then end the loop when an empty line is entered. This is I think for the user the most intuitive approach. All you have to do is to parse non empty strings with stringstreams (and eventually complain if non numeric values were entered).
An less perfect approach could be to instruct the user to enter some non numeric value to end the loop. You then have to clear the failure that invalid input would generate:
while (std::cin >> val ) {
...
}
if (std::cin.eof()) // display the special case
std::cout <<"End of file encountered !" << std::endl;
std::cout << "Press a key...";
std::cin.clear(); // clear the error state of cin
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
Surprisingly, this works compiled with MSVC2015 on windows when entering Ctr+Z: once the end of file state cleared the console is magically restored and you can continue to read. However you can't assume this to work with console front-ends like Notepad++, nor with other implementations of the standard library, nor on other OS.
while(!(cin >> ar[i]))
{
cin.clear(); // clears bad input
while(cin.get() != '\n')
continue;
cout << "Invalid input, please enter valid scores";
}
The above code is from a much larger file. I copied this bit of a code from one of my textbooks and I don't really feel comfortable using it as I do not understand how this works.
I am using it as a measure to handle input errors.
So ar is an empty array of integers, if I decide to enter 'k', then
!(cin >> ar[i])
is true.
From here I clear the input buffer (I think that is correct, I'd like someone to confirm or dispute this please). The terminal then prints "Invalid input..."
Now if I just press Enter nothing happens, but isn't Enter the newline char? So shouldn't the code read
while(cin.get() == '\n'
?
while(!(cin >> ar[i]))
This tries to parse a value from cin and store it in ar[i]. By default, >> skips whitespace first, then sees if the characters in cin describe a legal value for whatever the type of ar[i] is. If a legal value is found, then cin stream state remains good, and its operator bool() const will kick in given the boolean not/! operation, such that the while loop will break.
If parsing fails though, the stream state will be set to one or more of:
bad (if there's some unrecoverable stream error, like stdin supplied over a network connection that gets disconnected),
fail (if the characters just didn't form a legal value for the type), or
eof (end of file, for a "proper" shutdown/close of the input, as supplied by ^D in UNIX/Linux, ^Z in Windows, and the end of input when a program's invoked as in echo input | program).
All the above modalities are described under "State Functions" here.
If the loop is entered due to any of the error conditions above...
{
cin.clear(); // clears bad input
...this does NOT clear any input data from the stream, but does clear the bad, eof and fail state flags, after which further input attempts can be made, though a stream that was in bad or eof state is likely to immediately reenter that state when further input is attempted (but not always - some OS may allow successful input after an eof conditions for std::cin if the user types/generates an EOF code then types actual text again...
while(cin.get() != '\n')
continue;
This tries to read characters from the terminal until a newline \n is encountered. The idea's clearly to clear out the rest of the presumed unparse-able input that might have led to a fail condition earlier. Sadly, if the problem was, or becomes, a bad or eof condition then this loop will hang the program, spinning burning CPU to no avail.
cout << "Invalid input, please enter valid scores";
}
If the problem was simply a mistyped value and no bad or eof condition, then the cout will prompt for further input.
Now if I just press enter nothing happens, but isnt enter the newline char?
Whenever the outer loop is executing cin >> ar[i] it will skip whitespace, including any extra newlines you type, until it sees some input (which may need to be a full newline-terminated line to get flushed by the terminal or program feeding it to the program), or a bad or eof condition. The inner while-loop is not there to get rid of empty lines - it's trying to discard the line with presumed non-numeric text in it.
Corrected code:
while (!(std::cin >> ar[i]))
{
if (std::cin.bad() || std::cin.eof())
{
std::cerr << "Fatal error on cin while reading numbers\n";
exit(EXIT_FAILURE);
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid input, please enter valid scores\n: ";
}
The goal of this entire code is to keep printing errors and requesting input until the user enters a valid number before continue further into the program.
The loop that the entire code is enclosed in...
while(!(cin >> ar[i]))
says to loop if the input in the cin stream is invalid. Since ar is an array of integers, the input would be invalid if it is not a number.
cin.clear(); // clears bad input
When the cin stream encounters invalid input, the program begins executing the loop and continues to this line of code. Since the stream encountered invalid input, it has a flag that says there is an error. This requires that you, as the comment puts it, "clear bad input." Basically what this does is get rid of this flag. If this is not done, the flag will remain in the stream and the program will encounter another error next time the cin stream is used, regardless of whether or not the user input is valid.
while(cin.get() != '\n')
continue;
When the program took the input from the user, it took the string, char, whatever was the invalid input, but left the '\n' in the cin stream. To prevent errors the next time the cin stream is used, the program must get rid of that '\n', along with anything else that was lefty behind. cin.get() reads only one char from the cin input stream and returns it. Since the return value of this function is not being assigned to anything, all this does is discard the char that was read. In the case that more than the '\n' was left behind in the stream, this loop checks the value of the read char before disposing of it. This way, the loop keeps executing while the char that is read is NOT '\n'. Or in other words, it loops until the char that is read IS '\n'. The only thing that continue does, is tell the program to skip the rest of the current iteration of the loop and start the next iteration. In this situation, this is equivalent to giving the loop an empty body. You could very well replace continue; with {} and the program would do the exact same thing.
cout << "Invalid input, please enter valid scores";
The program has cleared the flag in cin and has also cleared any data from cin that may have been left behind. Now that all the errors from the invalid input have been handled, there is only one more thing to do. It's time to notify he user that the input was invalid and request new input. If the user enters more invalid input, the loop repeats. If the user enters valid input, the program continues on to the next line of code.
simply trying to compare two user defined vectors to see if they are equal, current code:
vector<int> ivec1, ivec2; //vectors, uninitialized
int temp1;
cout << "Enter integers to be stored in ivec1." << endl;
while(cin >> temp1) //takes input from user and creates new element in the vector to store it
{
ivec1.push_back(temp1);
}
int temp2;
cout << "Enter integers to be stored in ivec2." << endl;
while(cin >> temp2) //same as above with different vector
{
ivec2.push_back(temp2);
}
if(ivec1 == ivec2)
cout << "ivec1 and ivec2 are equal!" << endl;
else
cout << "ivec1 and ivec2 are NOT equal!" << endl;
So far it lets me assign values to ivec1 just fine, but as I exit the while loop by entering a letter to make cin fail, it skips the second while block. Out of curiosity I tried putting in other cin statements after the first while loop, and it ignores them all as well.
Does forcing cin to fail cause the program to ignore all other calls for it or something, or is there another problem? If so, how can I get this program to do what I want?
screenshot for your viewing pleasure:
http://img695.imageshack.us/img695/2677/cinfailure.png
*PS. having temp1 and temp2 was just me trying to figure out if using the same int for both assignment loops was causing the problem, anyway I just figured I'd leave it there
You would have to do cin.clear() to reset the stream state. Then you will have to make sure that the offending character is read from the stream (using one of the techniques described here), so that the next input operation does not fail as well.
You mean that you a doing a ctrl-D to give end-of-file for the first loop.
The problem with that is that once EOF is achived it will persist and the second loop will also see the EOF and never read anything.
Instead use a terminating charater such as a blank line or a '.' and specifically test for that in toy while loop instead of while (cin >> tmp1)
Use cin.clear() between the loops. This command resets the state of the stream back to a usable one.
Might be helpful to know that you don't always have to enter an invalid character to exit a loop, you can also use (on windows) a ctrl-z (ctrl-d on other systems) on the console, which stimulates an EOF. You'd still have to cin.clear() (because an EOF still invalidates the stream) - but it's not as dangerous
When the first while loop exits because of failure of std::cin, it also sets the failure flag internally. All you need to clear that flag by writing the following after the first while loop:
scin.clear();
It clears all the failure flag, so that cin can be used to read further inputs.
I found this when I was working through the same problem. I had to add cin.clear() and cin.ignore() to reset the stream between loops and have it recognize the 'cin' calls again.
Does anyone knows why C instruction is being reordered when cin cout and gets is used consecutively here?
I am using Dev-C++ 4.9.9.2.
#include<iostream>
using namespace std;
int main(){
char a[10],b;
for(;;){
cout<<"\ncin>>b:";
cin>>b;
cout<<"gets(a):";
gets(a);
cout<<"cout<<a<<b:"<<a<<" "<<b<<"\n\n";
}
}
I got an output like:
cin>>b:132
gets(a):cout<<a<<b:32 1
cin>>b:465
gets(a):cout<<a<<b:65 4
cin>>b:312242
gets(a):cout<<a<<b:12242 3
cin>>b:1
gets(a):cout<<a<<b: 1
cin>>b:
It seemed like some input for cin was passed in gets.. and it also appears that instructions were reordered like:
cin>>b;
gets(a);
cout<<"gets(a):";
instead of,
cin>>b;
cout<<"gets(a):";
gets(a);
cin>>b read just a character, leaving the rest of the input to be read by later input operation. So gets sill has something to read and don't block.
At the first cin >> b, there is no input available. You enter '132\n' (input from terminal is usually made line by line) in a buffer and just get the 1 out of it. gets reads the next characters 32 and the \n which terminates gets. It doesn't need to read something more from the terminal.
Nothing has been re-ordered.
your input from keyboard has been send only when you pressed enter. At that time, there have been enough data to execute the cin<<b, the following cout, then to complete the gets(a).
In others words, the execution of cin<<b is suspended to the reception of a char. But that char is not send to the program until you pressed 'Enter' (this is because of your terminal settings). When you press 'Enter', the first char is received by cin<<b and the remaining is buffered. cout executes, and when it is the turn of gets(a), the buffer delivers the remaining chars included the carriage return, so gets(a) completes as well, with the data you entered to complete the cin<<b instruction.
Try to simply press enter for the cin<<b to complete, then you'll see the cout, and then you will have the gets(a) waiting for your inputs.
While not really answering your question...
The idiomatic way in C++ would rather be to use getline. It's an accident of history that does not make it part of the iostream interface directly, but it really is the function to use for inputs.
Shameless plug from the website:
// getline with strings
#include <iostream>
#include <string>
int main () {
std::string str;
std::cout << "Please enter full name: ";
getline (std::cin,str);
std::cout << "Thank you, " << str << ".\n";
}
The main advantage of getline, in this version, is that it reads up until it encounters a line-ending character.
You can specify your own set of "line-ending" characters in the overload accepting a third parameter, to make it stop on commas or colons, for example.
The code isn't reordered, but std::cout is buffered so the string doesn't appear immediately on your display. Therefore gets(a) will be executed with the output still in the buffer.
You can add a <<flush after the output string to make cout flush it's buffer.
When you use std::cin, it knows how to tell std::cout to flush the buffer before the input starts, so you don't have to.
I'm a bit confused by the results of the following function:
int main() {
string command;
while(1) {
cin >> command;
if(command == "end")
return 0;
else
cout << "Could you repeat the command?" << endl;
}
return 0;
}
First of all - the output line ("could you...") repeats once for each individual word in the input (stored in command). So far as I can see, it should only be possible for it to happen once for each instance of the loop.
Also, when the line 'if(command == "end")' is changed to 'if(command == "that's all")' it never triggers. A little testing suggested that all of the whitespace was removed from the command.
Could someone explain to me what's going on here?
Thanks
The formatted input operator >>() reads space separated tokens from input. If you want to read whole lines, use the getline() function:
string command;
getline( cin, command );
Most (possibly all) operating systems buffer input. When you type a string of words and then hit [enter] it is only at the time you hit enter that the input is usually passed to your program. Thus that is when it will start reading the input and separating it out into individual words (because as Neil mentions, the >> reads words, not lines). Thus your program goes through the loop multiple times (once per word you had in the line) even though you only hit enter once.
So, you are correct when you think it should only display "could you..." once per loop. That is what is happening.
Likewise, you'll never have a command that contains more than one word because of the space delimiter. As mentioned, use getline() to retrieve the entire text for the line you entered.