Update
I found the cause of the problem. I have been experimenting with the fish shell. I saw the comment that said someone had successfully run my code on a Mac, and decided to try it in a standard bash shell. It worked perfectly. So, no more fish shell I guess. 🙂
I would still appreciate knowing how and why cin works the way it does. This is the main part of my question.
I have run into a popular problem: using cin in a loop. The code is straightforward, but I cannot find a solution. The answers Google have provided me are varied, but usually involve some combination of cin.clear(), cin.ignore(), and cin.get(). Unfortunately, I haven’t been able to find a combination or ordering of those that fix my problem. Moreover, I find it frustrating that I don’t have a complete understanding of the function of cin. I’d rather not use trial and error to fix this. I want to understand exactly what’s going on.
What Should Happen
When I run my code, I should see a prompt with a list of options. I should be able to type a character which will run one of the options. Then, it should display the prompt again and repeat the process until I select the Exit option.
What Actually Happens
As soon as I run the code, it prints the prompt to the screen an arbitrary number of times and eventually stops halfway through the prompt. Then I am unable to do anything but kill it with ^C.
$ ./run
Choose an option:
[A]dd a score
[R]emove a player
[E]xit
: That is not a valid input.
[repeated a bunch of times]
Choose an option:
[A]dd a score
[R]emove a player
[E]xit
: That is not a valid input.
Choose ^C
$
My Question
What causes cin to do that? As an experienced Java developer (but a beginner C++ developer), I’m familiar with the concepts of buffers and streams and such, but I have no idea how cin works. I know that cin.clear() clears an error state, and cin.ignore() ignores a number of characters in the stream. My Google-fu has thus far been unable to find a concise reference.
Why does cin act the way it does? How should one visualize what happens under the hood when using cin in a loop? What is the most elegant way to implement this infinite menu idea in C++?
My Code
Here is a simplified version of my code, which produces the exact same problem as the full version:
#include <iostream>
using namespace std;
int main () {
//infinite menu
char input;
while(true) {
//prompt
cout << "\n\nChoose an option:\n";
cout << "[A]dd a score\n";
cout << "[R]emove a player\n";
cout << "[E]xit\n";
cout << "\n\t: ";
//input
cin >> input;
//decide what the input means
switch(input) {
case 'a':
case 'A':
cout << "Add a score.\n";
break;
case 'r':
case 'R':
cout << "Remove a player.\n";
break;
case 'e':
case 'E':
cout << "Program Complete.\n";
return 0;
break;
default:
cout << "That is not a valid input.\n";
}
}
return 0;
}
I compile and run with:
$ g++ Test.cpp -o run
$ ./run
I’m running gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) on Mac OS X 10.8.2.
Do yourself a favour and don’t extract tokens directly from
std::cin. Instead, read line by line withgetlineand then interpret each line. Also, you must always evaluate the result of an input operation in a boolean context, or you will not be able to handle arbitrary input correctly.For a test, your program must survive if you call
echo "abc" | ./run. This should always be one of your first tests.Now, on to the code: