1
votes

So, I've looked around and haven't been able to figure out what's going on with cin during my While loop. I'm working through the book C++ Primer (5th edition) and I noticed that during one of the exercises I couldn't use cin to grab strings without it not terminating the while loop. I fixed this issue by just using getline().

The goal of the current exercise is to ask for user input from the values of 0 - 15, and converting that number into it's "Hex Equivelant" (Where 0 = 1, 1 = 2, 2 = 3, ... , 10 = A, 11 = B). I tried doing this without the book and failed, but then started questioning the code in the book. Here's the code in the book:

//Note: <iostream> and <string> have been included. using namespace std is used 
const string hexdigits = "0123456789ABCDEF";
cout << "Enter a series of numbers between 0 and 15"
     << " separated by spaces. Hit ENTER when finished: "
     << endl;
string result;
string::size_type n;

while(cin >> n)
    if (n < hexdigits.size())
        result += hexdigits[n];
cout << "Your hex number is: " << result << endl;

If I were to run this code, it would never terminate the while loop after hitting enter without entering any code (essentially giving the input of whitespace I would think?).

I'm here for two reasons:

1) Why does this code not work? 2) I would appreciate a nudge in the right direction, but not the answer to how to get this code to execute correctly

If I can't receive reason 1 without compromising reason 2, I would much rather have reason 1 be fulfilled.

Quick-Edit: I apologize, I'm using Visual Studio 2012

6
possible duplicate of the question on while (cin >> )Beta

6 Answers

0
votes

Hitting Enter produces either a CR or LF or both, depending on your platform. This is a valid input so satisfies the condition to continue the while loop. You will need to either explicitly test for these characters at the beginning of your input or use Ctrl-C to break out of the loop.

As a readability issue, I would include braces around the code that you want in the loop. What you have there is valid C++ since without braces the while will loop on the next statement and the whole if conditional is a single statement. Practice putting them in now even on single line loops and you'll save yourself some headache debugging in the future.

3
votes

As long as you enter valid numbers it will continue to read numbers. You can terminate the loop by entering something which isn't a number, e.g., "goodbye". At the beginning of a line, i.e., immediately after hitting enter you should also be able to terminate the standard input using Ctrl-Z (I think; I normally work on UNIX-like systems where you'd terminate the standard input using Ctrl-D).

Essentially, a stream converts to true as long as neither std::ios_base::failbit nor std::ios_base::badbit is set in its state (you can look at stream's state using stream.rdstate()). As long as you successfully read integers from the stream, it has no reason to go into failure state. When you enter something which isn't an integer, it will get std::ios_base::failbit set. Likewise, when it reaches the end of the stream.

1
votes

@Protomega, You can use the same code, but press Ctrl+D to stop input stream.

0
votes

There is an easier way to do this:

const string hexdigits = "0123456789ABCDEF";
cout << "Enter a series of numbers between 0 and 15 separated by spaces. Hit ENTER when finished: " << endl;
string line;
string result;
if (getline(cin, line)) // get the whole line
{
    istringstream iss(result); // break them by spaces
    int i;
    while (iss >> i)
    {
        result += hexdigits[i];
        result += " ";
    }
    cout << "Your hex result:  " << result << endl;
}
else
{
    cout << "Error handling input!" << endl;
}

With your solution, you would need to press Ctrl-D to end the input.

0
votes

CTRL-D works on Linux. A simpler code snippet is below:

vector<double> vd;
for (double d; cin>> d;)
     vd.push_back(d);
for(int i=0; i<vd.size(); ++i)
   cout << vd[i] << endl;
0
votes

In while (cin >> n) think separately of While() as a loop and what stands within it's parenthesis. When Loop begins you are moved into parentheses and asked to enter something by cin. This happens every time loop begins. There is no way to terminate looping in this case. It is the same as i would say:

while (/*some condition*/) {
cin >> n; // this is always valid, true
}