I am just working through the book Accelerated C++. (My problem is located on page 57, if you guys have the book with you)
The problem is the following:
We do have a function which reads student grades:
...
while (in >> x) { // in and x are defined as an istream& and as a double
hw.push_back(x); // hw is vector defined as vector<double>&
}
in.clear();
...
Now, in book and also on the cplusplus.com refernce is stated that the clear function resets all the error states and that the input is now again ready to read some input.
The problem is that if I put a:
int a = 0;
cin >> a;
cout << a << endl;
after the function it jumps the cin and just gives me a 0. Did I understand the function of cin.clear() totally wrong or what can I do to get the cin active again.
As I had the same problem a while before I read the book, I know that I solved the problem back then with the following line:
cin.ignore( numeric_limits<streamsize>::max(), '\n');
Of course I then have to hit an extra enter key but it eats all the stuff which comes before and which makes the cin not to work.
The thing is that neither .clear nor .ignore work properly alone but using them both together I am able to enter something for the variable a;
EDIT: Ok, here is the whole code. This is something I have written myself, which is not from the book.
istream& in = cin;
int var = 0;
vector<int> vec;
while ( in >> var ) {
vec.push_back(var);
}
for (int f = 0; f < vec.size(); ++f) {
cout << vec[f] << endl;
}
cin.clear();
cout << "cleared" << endl;
int a = 0;
cin >> a;
cout << a << endl;
The call to clear clears the error state set by a failed read. It doesn't do anything with the characters that might be present in the input stream.
If the error state is a result of failing to read a double, it is likely that the next character will also fail as an integer.
If you try
char ch;
cin >> ch;
I'm sure that will work better.
Otherwise you will have to ignore some characters to get rid of the unreadable input.
The while loop in your code example reads integer values until the end of input or an error occurs while reading, e.g. giving a character that cannot occur as an integer digit like 'q'.
When an error occured, you might have a chance to recover from that error by calling clear() and then removing the offending character from cin's input buffer:
char dummy;
cin >> dymmy;
Then you can read an int again.
Related
I have gone through many existing answers here StackOverflow, but I am still stuck.
code:
int c;
cin >> c;
if(cin.fail()) {
cout << "Wrong Input";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else
{
cout << c*2;
}
If I enter wring input e.g s instead of an integer, it outputs Wrong Input. However, if I enter an integer, and then I enter a string, it ignores the string and keep outputting the previous integer result, hence it does not clears the cin buffer, and the old value of c keeps on executing.
Can anyone please suggest the best way other than cin.ignore() as it does not seem to work.
and yeah for me, the max() in cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); gives error. So this does not work either.
the max() function needs to be defined in the beginning of the file. cin.ignore() works very well to clear the buffer, however you need the numeric limits function max(), which in my case was giving error.
Solution:
#ifdef max
#define max
#endif
add these lines on the top, and a function such as following will work fine.
int id;
bool b;
do {
cout << "Enter id: ";
cin >> id;
b = cin.fail();
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while ( b == true);
P.S: Thanks #Nathan
I need to read an unknown length sequence of integers and then i need to find the longest monotonic subsequence in it. The sequence ends with EOF sign and its elements are to separated with spaces.
I'm not really bothering the algorytm of finding the subsequence now I'd like to make sure that I'm reading elements of the sequence in a right way. Below is a code which is supposed to do the job but there's a bug which I don't get right now.
#include <iostream>
using namespace std;
int main()
{
int sum=0;
int a=0;
cout << "Give me a number: ";
// while (!fin.eof()) {
while (cin >> a) {
cin >> a;
sum +=a;
cout << "Sum is: " <<sum << endl;
/* Thats the place where whole magic is supposed to happen.
I'm really confused however, because after entering i.e. 2 3 4 2 4
and pressing <Enter> five times shows an answer "The sum is <proper sum>"
and the answer "The final sum is: ... " doesn't show at all.
*/
}
cout << "final sum is : " << sum;
cout << "Hello world!" << endl;
return 0;
}
I'll be very grateful if anyone could answer my questions and explain if and where I'm wrong.
I'll appreciate any help!
Well, for one, you seem to be checking on the state of fin, but you never open that file and you never read from it. I'm guessing you meant to use std::cin everywhere, or fin everywhere; I'll stick to std::cin, but fin would work the same way.
The problem is that you first check for end-of-file and then read and use the data. This means that if the read failed, you aren't told about this. Instead of
while (std::cin) {
std::cin >> a;
sum += a;
}
use
while (std::cin >> a) {
sum += a;
}
This will still perform the check, but after the read, meaning that if the read failed, you don't go into the body of the loop, and don't use the (nonsense) data.
The fin case looks much the same:
std::ifstream fin("mydata.txt");
while (fin >> a) {
sum += a;
}
Note that there's no need to explicitly check for whether you reached the end of the file; checking the state of the stream will catch that error, as well as any errors due to being unable to parse a number. If instead we did
while (fin >> a, !fin.eof())
this would correctly handle the case where you read the whole file, but loop infinitely if it contained something other than a number.
First, decide whether you're reading from the file (fin) or the program's input (std::cin). Currently, you're reading from one and checking the other for eof.
If you're reading from the file, then you'll need to open it. Otherwise, remove fin to avoid confusion.
Then you should check for eof (and other error conditions) after attempting to read, and before using the result:
while (std::cin >> a) { // or `fin`, if that's where you're reading from
// your code using 'a' here
}
I am a beginner programmer learning c++. I am having a nagging issue with the cin command.
In the program section below, if I enter a wrong type at the 1st cin command, the program will not execute any of the following cin commands at all, but will execute the rest of the program.
//start
#include <iostream>
using namespace std;
int main()
{
int x=0;
cout << endl << "Enter an integer" << endl;
//enter integer here. If wrong type is entered, goes to else
if (cin >> x){
cout << "The value is " << x << endl;
}
else {
cout << "You made a mistake" << endl; //executes
cin.ignore();
cin.clear();
}
cout << "Check 1" << endl; //executes
cin >> x; //skips
cout << "Check 2" << endl; //executes
cin >> x; //skips
return 0;
}
//end
Instead of the if else, if i put the same concept in a loop
while (!(cin >> x))
the program goes into an infinite loop upon enterring a wrong input.
Please help me explain this phenomenon, as the text book i am following says the code typed above should work as intended.
Thank you
cin is an input stream. If an error occurs cin goes into a let's call it "error occured" state. While in this state no character input can be made, your request to collect a character from the input stream will be ignored. With clear() you clear the error and the input stream stops ignoring you.
Here is the ignore function prototype
istream& ignore ( streamsize n = 1, int delim = EOF );
This function gets characters from the input stream and discards them, but you can't get any character if your stream is ignoring you, so you have to first clear() the stream then ignore() it.
Also, a note on the side: If someone inputs, for example "abc", on the first input request your cin gets only one character that is 'a' and "bc" stays in the buffer waiting to be picked up, but the next call to cin gets the 'b' and 'c' stays in the buffer, so you again end up with an error.
The problem with this example is that the cin.ignore() if no arguments are handed to it only ignores 1 character after you clear(). and the second cin gets 'c' so you still have a problem.
A general solution to this problem would be to call
cin.ignore(10000, '\n');
The first number just has to be some huge number that you don't expect someone would enter, I usually put in 10000.
This call makes sure that you pick up all the characters from the false input or that you pick up every character before the enter was pressed so your input stream doesn't get into the "error occurred" state twice.
You may also want to try
if ( std::cin.fail() )
as a backup to prevent a crash due to input of the wrong type when prompted
I am having trouble using the cin method to acquire a variable. When the input is a number there is no problem, but when it is a special character like a dot [.],
the whileloop loops into infinity.
What am I doing wrong?
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}
I searched for the answer and i should have to flush the buffer but i don"t get how to do it. I'm rather new with c++. Thanx
Make race an char, then you will be able do to:
while (*race < '1' || *race > '3')
which is probably what you want to achieve.
Explanation:
When you cin >> into an int, it converts given ASCII string to integer value. . doesn't have an integer meaning, so it isn't read into race and failbit is set - further >>s are no-op, until you clear them. However, if you cin >> into char and compare it with other chars (well, their ASCII codes, actually), you will be able to check it without troubles.
This example exactly reproduces your problem:
#include <iostream>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
std::cin >> i;
}
}
Here's what happens: When operator>> fails to read an integer (e.g. when you type a dot and press enter), whatever you typed stays in the stream, including the newline character.
So in the next iteration of the while loop the next input is already there and since it's not a valid integer, the loop can never break.
You need to make sure that, when operator>> fails, you empty the stream and clear all the error flags that got set.
#include <iostream>
#include <limits>
int main()
{
int i = 5;
while (i < 1 || i > 3)
{
if (!(std::cin >> i))
{
// clear streams internal error flags
std::cin.clear();
// ignore what's left in the stream, up to first newline character
// or the entire content, whichever comes first
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
There are several problems with your code. The first is that you don't
verify that your input has succeeded; the correct condition for the
while should be:
while ( !cin || (*race < 1 || *race > 3) )
As written, if the input fails (which is what is happening when you
enter a '.', supposing that race has type int*), then *race
contains its previous value, whatever that was.
The second is that if you do get an error from cin, you don't clear
it. Once the stream is in an error state, it stays that way until you
explicitly clear it. If cin has failed, you need to execute:
cin.clear();
somewhere in the loop.
The third is that if cin fails, you don't extract the character which
made it failed, so that after clearing the error status, you need to
extract it. Given the way you've structured your dialog, you probably
want to ignore everything until the end of the line:
cin.ignore( INT_MAX, '\n' );
You may want to do this even if cin didn't fail, either in the loop
(if entered because of the *race < 1 || *race > 3 condition), or in
case of success. Alternatively, you may want to shift to reading lines,
and ensure that the line only contains whitespace after the character
you're interested in.
This last solution is the one I would adopt, since it handles pretty
much all of the above problems. So my code would look something like:
// return -1 on error in input,
// throw exception on (unexpected) end of file
int
getRace( std::istream& source )
{
std::string line;
if ( !std::getline( source, line ) ) {
throw std::ios_base::failure( "Unexpected end of file" );
}
std::istringstream tmp( line );
int results;
return tmp >> results >> std::ws && tmp.get() == EOF
? results
: -1;
}
// ...
int race = -1;
while ( race < 0 ) {
std::cout << "What is your race\n"
"1. Human\n"
"2. Troll\n"
"3. Zombie\n" << std::flush;
race = getRace( std::cout );
if ( race < 0 ) {
std::cout << "Wrong choice" << std::endl;
}
}
Note that by inputting through a line, you avoid any problems with
resetting format errors, skipping erroneous input or resynchronizing in
case of error.
The other solution besides the one accepted is to clear the cin's failbit and ignore the last input like below:
cout << "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
while(*race<1||*race>3)
{
// Clears the state of cin to be in good state
cin.clear();
// Ignores the last input read so that it's not read back again
cin.ignore();
system("cls");
cout << "Wrong choice"<<endl<< "What is your race" <<endl<<"1.Human\n2.troll\n3.zombie"<<endl;
cin >> *race;
}
I can't seem to figure out why this falls into a loop after getting non-int input. I've tried cin.flush(), which doesn't seem to exist, cin.clear(), which seems like it should work, even cin.sync() after reading someone else post about it working, but didn't seem to make much sense. Also tried cin.bad().
Thank you very much for any help
Please enter the first number: f
Sorry, I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?Sorry,
you d on't get any more tries. Press
any key to continue . . .
#include <iostream>
using namespace std;
int main(){
int entry;
int attempts = 1;
int result;
while(attempts <= 5) {
try {
cout << "\n\nPlease enter the first number: ";
cin >> entry;
if (cin.fail())
throw "Sorry, I don't think that's a number?";
if (entry < 0)
throw "Sorry, no negative numbers. Try something else? ";
cout << "\nNow the second number: ";
cin >> entry;
cin.clear();
cin.get();
}
catch (char* error) {
cout << error;
attempts++;
}
}
if (attempts > 5)
cout << "Sorry, you don\'t get any more tries.\n";
system("pause");
return 0;
}
You should think carefully what you want to do if user gives invalid input in this case. Usually in these cases the best solution is to read one line from the input and throw it away.
Try putting cin.clear() and std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n'); in your catch clause. cin.clear() clears the failure state in cin, and cin.ignore() throws away rest of the line waiting in the input buffer.
(And yes, you probably should rethink your use of exceptions).
The most straight-forward (but not usually the easiest nor the fastest) way of dealing with validation of line-based input is to always read it line at a time. This way no extra whitespace (such as linefeed characters) is left unread in the buffer in any case, and discarding erroneous input is also quite automatic.
// Infinite loop for retrying until successful
while (true) {
// Ask the user something
std::cout << prompt;
// Read the answer (one full line)
std::string line;
if (!std::getline(std::cin, line))
throw std::runtime_error("End of input while expecting a value");
// Put the line read into iss for further parsing
std::istringstream iss(line);
int val;
// Read val from iss and verify that reading was successful and
// that all input was consumed
if (iss >> val && iss.get() == EOF) return val;
std::cout << "Invalid input, try again!\n";
}
It is fun to make a BASIC style input function out of this:
template <typename Val> void input(std::string const& prompt, Val& val) {
// (the above code goes here, slightly adjusted)
}
int main() {
int w;
double l;
input("Enter weight in kg: ", w);
input("Enter length in m: ", l);
std::cout << "BMI: " << w / (l * l) << std::endl;
}
Notes for the pedantics who were going to downvote me:
function input should be specialized for std::string
exceptions thrown by the input function should be caught in main
My Problem was to block char input to a cin >> number
This error caused an 'infinite' loop showing my prompt cout << prompt
with no way of exit but kill the process ...
The following shows what worked for me!
========================================
double fi_trap_d() // function to return a valid range double catching errors
{
double fi_game_sec;
//-------------------------------------------
do
{
fi_game_sec = -1;
cout << fi_game_sec_c;
//------------------------------
cin.ignore(); // (1)
//------------------------------
try
{ cin >> fi_game_sec; cin.clear(); } // (2)
catch (...) //out_of_range)
{
fi_game_sec = -1;
cout << " Dis am an error!\n";
// just loop back as we asked for a number
}
} while (fi_game_sec < 1);
//-------------------------------------------
return fi_game_sec;
}
========================================
Despite trying the " Dis am an error! " has NEVER shown up.
The key was (1) & (2) !
Exceptions should be used to handle exceptional, unexpected situations. Incorrect input from a user is neither unexpected nor exceptional -- it's more or less the norm. Personally, I tend to just ignore most bad input completely (when it can't be prevented). When (and only when) they enter something unusable repeatedly is it even worth pointing it out to them. As such, I'd tend to write the code something like:
char ch;
int attempts = 0;
std::cout << "Please enter the first number: ";
do {
cin >> ch;
attempts++;
if (attempts > 5)
std::cerr << "The only allowable inputs are '0' through '9'\n";
} while (cin.good() && !isdigit(ch));
int first_number = ch - '0';
This reads the input as a character, so it's always removed from the input stream. Then it attempts to validate the input, and if it fails, attempts to read again. Of course, you might want/need to get a little more elaborate, such as reading an entire line, attempting to convert it to a number, and reading another line if that fails.
Why are you doing this with exceptions? You're not going to kill the program on input, so you shouldn't throw an exception.
Just print out your error message and attempt to read in again.
It looks like you would be better off with iostream's native exceptions. Enable with
cin.exceptions( ios::failbit );
try {
…
} catch( ios_base::failure & ) {
cin.clear();
…
}
Never, ever throw an an object not derived from std::exception, and especially not a native type like char*.