Meaning of cin.fail() in C++? - c++

while (!correct)
{
cout << "Please enter an angle value => ";
cin >> value; //request user to input a value
if(cin.fail()) // LINE 7
{
cin.clear(); // LINE 9
while(cin.get() != '\n'); // LINE 10
textcolor(WHITE);
cout << "Please enter a valid value. "<< endl;
correct = false;
}
else
{
cin.ignore(); // LINE 18
correct =true;
}
}
Hi, this is part of the code that I have written.
The purpose of this code is to restrict users to input numbers like 10,10.00 etc,
if they input values like (abc,!$#,etc...) the code will request users to reenter the values.
In order to perform this function( restrict user to input valid valus), I get some tips and guides through forums.
I think is my responsibility to learn and understand what these codes do... since this is the first time I use this code.
can someone briefly explain to me what does the codes in
line 7,9,10, and 18 do? Especially line 10. I got a brief idea on others line just line 10 I don't know what it did.
Thanks for your guides, I appreciate that!

cin.fail() tells you if "something failed" in a previous input operation. I beleive there are four recognised states of an input stream: bad, good, eof and fail (but fail and bad can be set at the same time, for example).
cin.clear() resets the state to good.
while(cin.get() != '\n') ; will read until the end of the current input line.
cin.ignore(); will skip until the next newline, so is very similar to while(cin.get() != '\n');.
The whole code should check for end of file too, or it will hang (loop forever with failure) if no correct input is given and the input is "ended" (e.g. CTRL-Z or CTRL-D depending on platform).

// LINE 7: cin.fail() detects whether the value entered fits the value defined in the variable.
// LINE 18: cin leaves the newline character in the stream. Adding cin.ignore() to the next line clears/ignores the newline from the stream.

For line 7 and line 9, read the document.
while(cin.get() != '\n'); // LINE 10
in the while, it tests whether the line cin.get() is an empty line, i.e, containing just the new line.

Line 7: test if entered data is correct (can be read as decltype(value)). cin.fail() is always true if some error with the stream happened. Later, in
line 9: you clear cin state from bad to previous, normal state. (recover after the error). You cannot read data anymore until recovering from the bad state.
Line 10: you read until the end of line. Basically you skip one line from the input
Line 18: this line executes only if entered data is corrected. It reads and discards one line from stdin.

while(cin.get() != '\n'): All string in c are null terminated. This means that \n is the end of all the string objects. Lets say you have string "this" for c it is this\n, each alphabet being stored in a char type. Please read along
http://www.functionx.com/cpp/Lesson16.htm
cin.fail(): cin.fail() detects whether the value entered fits the value defined in the variable.
read:http://www.cplusplus.com/forum/beginner/2957/
cin.ignore(): Extracts characters from the input sequence and discards them
http://www.cplusplus.com/reference/istream/istream/ignore/

I know it's not usual in Stack Overflow to just list links, so I'll give a bit more detail, but this answer really boils down to a bunch of links.
For line 7, just google cin.fail. Here's a good reference, and what it says:
Returns true if either (or both) the failbit or the badbit error state flags is set for the stream.
At least one of these flags is set when some error other than reaching the End-Of-File occurs during an input operation.
failbit is generally set by an operation when the error is related to the internal logic of the operation itself; further operations on the stream may be possible. While badbit is generally set when the error involves the loss of integrity of the stream, which is likely to persist even if a different operation is attempted on the stream. badbit can be checked independently by calling member function bad:
One line translation: it tells you if there was an unexpected error while trying to read the input stream.
You can find similar references for cin.ignore, cin.clear and cin.get. The quick summary:
cin.ignore - ignore one single character present in the stream.
cin.clear - clear any error flags in the stream
cin.get - get one character at a time, until you hit the newline '\n' character.

The standard input stream (cin) can fail due to a number of reasons.
For example, if value is an int, and the user enters a large number like
124812471571258125, cin >> value will fail because the number is too big to fit inside an int.
But:
There is a much simpler way to do what you want. You want the user to enter only valid floating-point values, e.g. 10 or 10.00, but no characters, right? So you can just do this:
double value;
cout << "Please enter an angle value: " << endl;
while (!(cin >> value)) { //Since value is a double, (cin >> value) will be true only if the user enters a valid value that can be put inside a double
cout << "Please enter a valid value:" << endl;
}
This does the same thing that your code does, but much more simply.
If you're interested in what other things can cause cin to fail, look here:
http://www.cplusplus.com/forum/beginner/2957/

Related

Ending a while loop in command prompt

This is an excerpt from the Competitive Programmer's Handbook by Antti Laaksonen:
If the amount of data is unknown, the following loop is useful:
while (cin >> x) {
// code
}
This loop reads elements from the input one after another, until
there is no more data available in the input.
My question is how do we end such a loop in the command prompt, where the prompt takes one input at a time? By pressing enter, the prompt asks for new input and not terminating the input.
Edit: I have tried using ctrl + D/Z but I am getting this:
In order for that loop to end, cin needs to enter a failed state. That will cause it to evaluate to false and stop the loop. You have a couple ways you can do that. First is to send bad input, which will cause cin to fail and end the loop. Since you are excepting integers, you could just input a letter and that will cause it to break.
Another option is to send the EOF (end of file) signal to cin You can do that using ctrl+D (windows) or ctrl+Z (linux) and the pressing enter. cin will stop reading once it sees it has reachged the EOF and it will enter a failed state and cause the loop to end.
It should be noted that with both of these options that if you want to use cin again after you do this you will need to call clear() to remove the error flags and if you entered bad input, you will need to use ignore() to remove the bad input from the stream.
My question is how do we end such a loop in the command prompt, where the prompt takes one input at a time?
Note that cin >> x; returns cin. This means when you write
while(cin >> x)
you do the >> operation into x and then check cin.
When the user enters an input whose type differs from the type of variable x, then this while loop will end automatically. This is because cin will not be in a valid state anymore and hence cin >> x will become false . Basically the loop ends when the state of the stream is set to failed. Like supplying a different type value or when EOF is encountered.
There is other way to end such a loop from inside the while block by using break .

in c++ program after pressing enter , "cin" will feed all Variables

I have a program that takes two numbers and shows them on the screen.
However, when I hit "enter" after I input the first number, my program shows the answers before letting me input the second number.
Why does this happen?
int main()
{
int n1;
float n2;
cin>>n1;
cin>>n2;
cout<<"int n:"<<n1<<endl<<"float n:"<<n2;
return 0;
}
I wanna input 0.25 and 35 but when I write 0.25 and hit enter suddenly shows the answer "int: n:0 float n:0.25" it doesn't let me write second num. my os is Win10 and this program compiled with DevCpp
It works when both variables are ints.
There is no difference between cin>>n1; cin>>n2; and cin >> n1 >>n2. Enter key only serves as signal to sychronize input buffer and stream buffer. cin doesn't input per line, it parses buffer when there is available volume of data. If parse incomplete, it waits. If parse can't be done, it stops and state bit changes. To continue parsing you have either ignore or clear part or whole buffer content.
Something wrong was entered in first line, causing cin to go into bad() state. Edge case might happen if you're running program through a remote terminal, some incorrect character could slip in, e.g. ^M generated by new line from Windows would break cin stream on Linux. That's also case if you input from a file which was saved on different platform. On Windows line ends consist of two characters, #10 and #13. On linux steams expect only #13 as a new line and buffer flush signal, #10 is an unexpected character.
Edit (after OP gave information about input data):
"0.25" would be parsed as "0" and ".25", that expected and documented stream behavior. Parsing for n1 had stopped as soon as stream encountered character which doesn't fit int pattern, which could be space, end of line, alphabetic or punctuation. Period considered a punctuation in this case
Then it tries to get a float from stream input and buffer contains ".25". It's a legal float notation and it gets assigned to n2.
When you have both "int", you cannot get second value at all with same input, it always will be 0, because cin locks up in bad state, i.e. method its istream::good() returns false. You have to check state of stream after reading variables. Any further formatted reading that wouldn't be able to parse .25 wouldn't advance stream past that point.
If you want to read from stream exclusively line by line, you have to use istream::getline() method to get the string. There is also method get which can acquire content of stream and ignore which allows to discard part of stream.

Failcheck message gets repeated for the same amount of invalid characters contained inside the wcin

I am currently getting back to programming and started with a simple second degree equation calculator. I'm getting an unexpected behavior which I have no idea why is happening.
I have a while that checks if the values of a, b and c are numerical, with a fail message if they are not. But the fail message gets repeated for the same amount of invalid characters inside the unacceptable input.
Here is the code:
wcout << "Insert a value for a: \n";
wcin >> a;
while (wcin.fail())
{
wcin.clear();
wcin.ignore();
wcout << L"Please insert a numerical value.\n";
wcin >> a;
}
Example of the problem described.
If someone knows what is going on, I'd appreciate the help
EDIT: I am using wcout and wcin because of UNICODE characters such as letters with accent marks and greek symbols. I don't know if this problem could be related to this, but often I get the error saying "wcin/wcout is ambiguous"
While wcin.clear() only sets the stream error state flags, the input stream must be reset, for example by wcin.ignore(...)
If you use wcin.ignore() it will use default parameters (see here): one character or the end of file condition.
Entering "aaa" will only extract an 'a', the rest remain in the input, which will be re-tested again in the next while-loop.
Entering from the console usually implies the 'Enter' key, whose character is '\n'. This is the delimiter we need to use to reset the input:
wcin.ignore(100, '\n');
Notice I've written 100. If you want to discard any number of characters then you need:
#include <limits>
....
wcin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Why do I have to press enter Twice?

For some reason in my program when I reach a certain spot, I have to press Enter twice in order to get it to submit. I added the clear to keep it from skipping input and the ignore() to keep it from keeping any extra characters in the buffer. I enter my input and then it drops down to a new line, I hit Enter again and it enter the input and continues the program no problem but I'm wondering why. Here's a code snippet:
cin.ignore();
cout << "Enter Student Major (ex. COSC): ";
cin.getline(student.major, 6);
for(int i = 0; i < sizeof(student.major); i++)
student.major[i] = toupper(student.major[i]);
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Any suggestions?
It seems to me that you are tossing too many cin.ignore() around, not knowing exactly why they are needed and when to put them there.
There are two common circumstances where cin.ignore() is needed to "make input work right":
when mixing formatted and unformatted input;
to recover from a formatted input error.
In both cases, you want to get rid of spurious characters from the input buffer; if there isn't any such character (which is probably what happens in your program), cin.ignore() will pause the execution and wait for user input - after all, you asked it to ignore some characters, and dammit, it will obey to its orders.
(although ignore() by default would "eat" just one character, whatever it may be, the execution is paused until a newline is found because by default cin is line buffered - new input is not examined until a newline is recieved)
Case 1:
cin.ignore() calls are often needed if you are performing an unformatted input operation (like getline) after performing a formatted input operation (i.e. using the >> operator).
This happens because the >> operator leaves the newline in the input buffer; that's not a problem if you are performing only formatted input operations (by default they skip all the whitespace before trying to interpret the input), but it's a problem if afterwards you do unformatted input: getline by default reads until it finds a newline, so the "spurious newline" left will make it stop reading immediately.
So, here you will usually call cin.ignore(...) call to get rid of the newline just after the last formatted input operation you do in a row, guaranteeing that the input buffer is empty. Afterwards, you can call getline directly without fear, knowing that you left the buffer empty.
It's a bad idea, instead, to put it before any getline, as you seem to do in your code, since there may be code paths that lead to that getline that have the input buffer clean, so the ignore call will block.
Case 2:
when istream encounters an error in a formatted input operations, it leaves the "bad" characters in the buffer, so if you retry the operation you get stuck endlessly, since the offenders are still there. The usual clear()/ignore() idiom comes to the rescue, removing the whole offending line from the input buffer.
Again, you don't put the clear()/ignore() sequence at random, but only after you get an input error from a formatted input operation (which sets the failbit of the stream).
Now, aside from these cases, it's uncommon to use cin.ignore() (unless you actually want to skip characters); don't spread it around randomly "just to be safe", because otherwise you will encounter the problem you described.
The answer can be found here.
The extraction ends when n characters have been extracted and discarded or when the character delim is found, whichever comes first. In the latter case, the delim character itself is also extracted.
So in your case, the program will not continue until a '\n' character is received.
I think cin.ignore(numeric_limits<streamsize>::max(), '\n'); is expecting a \n in the input and it doesn't find it, so you have to press Enter again for it to find it.

Run Time Error: Program skipping prompt for second and third names [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Program is skipping over Getline() without taking user input
Alright, so I have a program that is running and at the start it prompts you for the data fill the data members. The program does this for 3 different objects.
My problem is that, at run time, after inputting data for the fist object the program proceeds to skip input for the second name and goes straight to the next option. It does the same thing for the third option's name. It also does this when you get the chance to change the data.
"Enter CD Name: Microsoft Word
1-Game
2-Word
3-Compiler
4-Spreadsheet
5-Dbase
6-Presentation
Enter the number that corresponds with the CD's Type: 2
Input CD Cost: 15.23
Enter CD Name: 1-Game <- ((Skips the input part and takes you directly to the menu!))
2-Word
3-Compiler
4-Spreadsheet
5-Dbase
6-Presentation
Enter the number that corresponds with the CD's Type:"
The issue is most likely in my member function, but I'm not sure what the issue is.
Here's my member function code:
void CDX::LoadInfo() //Prompts, validates and sets data members
{
cout << "Enter CD Name: ";
getline(cin, Name);
int choice=0;
do
{ cout << "1-Game\n2-Word\n3-Compiler\n4-Spreadsheet\n5-Dbase\n6-Presentation" << endl;
cout << "Enter the number that corresponds with the CD's Type: ";
cin >> choice;
} while ((choice <1)||(choice>6));
switch(choice)
//Code for case-switch statement goes here)
So what am I missing? Is this a buffer issue or am I prematurely ending the code in some way that causes it to skip?
The conversion of a number stops when it finds a character that can't be converted.
In that case, the character is '\n'
When you use getline to read a line, this character is read and discarded, but when you read a number, it is read (to know if the number continues or not) and if it is not part of the number, it is left in buffer for the next read.
Example:
If you write:
"29312"
and press enter, your buffer will be filled with
"29312\n".
If you use cin >> number, to read stdin, it will consume the digits, but will left in the buffer the "\n".
In the next time you call getline, it will read an empty line that was left in the buffer.
I think it's because the first 'getline(cin, Name)' gobbles up the last newline keypress. When you enter the cost and press ENTER, the call to getline is completed.
You can keep an extra getline after taking the cost so that it consumes the newline. Then, I think, it will run correctly.
You have read the "CD Cost", but the newline remains in the input buffer. Skip whitespace before reading the CD name:
ws(cin);