Reputation: 8747
In this case, when the line marked hang point
receives invalid input, eg. abc
, it repeats the inner do-while loop and hangs upon reaching that line again.
// figure 1
std::string s;
do {
do {
std::cout<<"s = ";
std::getline(std::cin, s);
} while (s == "");
double d;
std::cout<<"d = ";
do {
std::cin.clear();
std::cin>>d; // hang point
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while (std::cin.fail());
} while (s != "exit");
In this case the program skips over that line and repeats the do-while loop forever.
// figure 2
double d;
do {
std::cout<<"d = ";
std::cin.clear();
std::cin>>d; // skip point
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while (std::cin.fail());
Why?
Originally I was going to ask why figure 1
hangs, and in the process of trying to simplify the example I came up with figure 2
, and found that it didn't hang, but repeated forever. I don't understand why either figure 1
or figure 2
do what they do.
Edit: I've been causing cin
to fail by entering alphabetical data at the prompt that I wrote for myself. eg.
s = something
d = 3
s = something
d = a
Upvotes: 0
Views: 1226
Reputation: 445
My impression is that you're resetting the flags, but the cin buffer is still full. So when it re-enters the loop, 'd' is automatically reassigned the letter value (say, the 'abc' you entered at the terminal) automatically. Thus the fail flag will then be reset, and the cycle repeats all over again.
Here's the fixed version (with a few stylistic changes, sorry about that):
#include <string>
#include <iostream>
int main(){
std::string s="";
std::string dummy="";
while ( s!="exit"){
s="";
while (s==""){
std::cout<<"s = ";
std::getline(std::cin, s);
}
double d;
std::cout<<"d = ";
do {
if (std::cin.fail()){
std::cin.clear();
std::getline(std::cin, dummy);
std::cout << "d = ";
}
std::cin>>d;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while (std::cin.fail());
}
}
Upvotes: 1
Reputation: 154
Figure2: You have to call cin.clear() before cin.ignore(). Otherwise, cin.ignore won't do anything because cin is still in an error state.
double d;
do {
if (std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout<<"d = ";
std::cin>>d;
} while (std::cin.fail());
Upvotes: 2