This question already has an answer here:
Is it possible to read an empty string from cin and still get true from cin.good()?
(1 answer)
Closed 7 years ago.
I am following the C++ primer book, and got curious about the following code example:
string buf;
while (cin >> buf && !buf.empty()) {
if (buf[0] != '_')
continue; // get another input
//the input starts with an underscore; process buf . . .
}
The loop should ignore words that do not start with an underscore and do something with the ones that do start with an underscore.
My question is about the condition
(cin >> buf && !buf.empty())
I would say that the condition (!buf.empty()) is always true when (cin >> buf) is true, so I do not see the point of adding it.
Is there any case when the second condition is not redundant?
There is a previous question on stack overflow about a similar construction (Is it possible to read an empty string from cin and still get true from cin.good()?) whose answer is simply no (the second condition is redundant).
If this is correct, why is it on the book? It is simply an error?
Or there is some special situation were the double condition makes sense?
just to be clear, operator bool() is badbit || failbit, and the failbit is set when "an input operation failed to read the expected charchter or any other kind of operation failed to produce the desired result" (Langer, Kreft 1999)
string buf;
while ((cin >> buf,cin.operator bool()) && !buf.empty()) {
if (buf[0] != '_')
continue; // get another input
//the input starts with an underscore; process buf . . .
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Can you explain how does it work, especially while (!(cin >> n) || (cin.peek() != '\n') ?
If I input numbers(1,2,3..) it works.If I input letters (a,b,c,d),it says me to enter one more time.
while (!(cin >> n) || (cin.peek() != '\n'))
{
cin.clear();
cin.ignore(256, '\n');
cout << "enter n ";
}
The first condition in the while loop
!(cin >> n)
checks whether the input was successful.
The second condition
(cin.peek() != '\n')
whether after the input the buffer contains the new line character '\n' that is whether the user pressed the Enter key.
For example if the buffer contains
123A\n
then if an object of an integral type is read then it can get the value 123 and the first condition will evaluate to true though as you see the input in general is invalid.
So this while loop excludes such a situation though if the user appends the input with a blank like
123_\n
where the underscore means a blank then this input also will be rejected. The only valid input is
123\n
That is the loop requires that the user entered a number without any additional symbols after the number and press the Enter key.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have the code below, so basically my problem is: when someone input a character like 'a', it will pop a message that requires a re-input
I tried using the ASCII:
if (a >= 97 && a <= 122) but it still didn't work
double a;
cin >> a;
if (a >= 'a' && a <= 'z')
{
cout << "Wrong input, please re-input a: " << endl;
cin >> a;
}
cout << a;
I expect it to pop the message to re-input but the actual output is always 0 no matter what character I input
The state of a stream can be checked by using it directly in a condition. If all is okay it "returns" true, otherwise "false". So you can do e.g.
if (!(cin >> a))
{
// Invalid input, or other error
}
On invalid input you need to clear the state.
Note that if the input is invalid then the input will not be read, and the next time you attempt to read you will read the exact same input that failed the first time. One way to solve it is to ignore the rest of the line. Another is to read a whole line into a string that you then put into an input string stream for the parsing of the input.
I'm currently learning c++ and i cant get my head around this syntax for the for loop.
I'm aware that for(<T>: <V>) (for-each) and the standard for(init; cond; incr) but i haven't come across the following before
for (char ch; cin>>ch && !isdigit(ch); )
If someone could shed some light onto it it would be greatly appreciated!
for (char ch; cin>>ch && !isdigit(ch); )
^^ A ^^ ^^^^^^^^ B ^^^^^^^^^^^^ ^ C ^
A: Is the init section but in this case it only declared a char named ch
B: Is the condition section executed on each iteration
It starts be taking a single character as input and then continues looping if it is not a digit
C: Is the increment section but is empty, the condition section is relied upon to get the next input (i.e., the increment) and cause the loop's termination
This is the same syntax as your second example:
for ( init ; cond ; incr)
for (char ch; cin>>ch && !isdigit(ch); )
This just default-initializes a char, then reads a new value in and ensures it's a digit each iteration.
for (char ch; cin>>ch && !isdigit(ch); )
Is your standard 3 part for loop. char ch; declares a char called ch. The condition of the the loop is the result of cin>>ch logically and with !isdigit(ch) and there is nothing being incremented.
The result of this for loop is it will read in input until the input is a digit or it reaches the end if the input.
A for loop does not need to have something in each part. As an extreme if you write for(;;) you would have a loop that runs forever.
It is.
The first value is simply an initialization value (char ch will remain unchanged, but simply be defined).
The second value is a value that has to be true for the loop to end (condition) - so until cin >> ch is not null (it gains a value) and until ch isn't a digit, it will run.
The third parameter is an increment, that is a void in your case, so nothing happens.
EDIT: I remember back in C++ classes in 1st year of college, my teacher would do something like:
for(int i = 0; i < 10; cout << array[i++]);
and basically shrinking the code by a line.
This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 7 years ago.
I have a file containing only one character 1 (there is no newline symbol after it)
Reading the contents with this method:
int value;
ifstream in("somefile");
for (!in.eof())
{
in >> value;
cout << "input: " << value << " , eof" << in.eof() << "'\n";
}
gives me the following output:
input: 1 , eof: 0
input: 1 , eof: 1
The questions are:
1) Why EOF flag is not set after first reading try? I mean, if program successfully reads the number on the first try, it somehow knows that the string representatiion of it is over. To find it out it has to try read at least one byte after 1 character and there it should have hitted EOF. Why that doesn' happen?
2) That said, if I have a file with one value per line, I always do have a duplicate of last input. Does it mean that I always have to discard it in any way and that would be correct? Or for example add extra check for EOF after in >> value; and only if it succeeds, do any logic I want?
I know that I can work around with readline() or while(in >> value) methods but it's more a question of understanding what really happens there.
Thank you.
This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 9 years ago.
I am compiling the following code under Microsoft Visual Studio 2013
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream in("filename.txt");
int n;
while (!in.eof()) {
in >> n;
cout << n << endl;
}
return 0;
}
filename.txt contains:
4
note: the second line is empty line.
I am getting this output:
4
4
My question is: Why 4 is duplicated in the output when I add trailing spaces or empty lines to the end of the file? and why eof is not working properly in this case?
Using !eof(), !fail(), !bad(), or !good(), is invariably the wrong way to condition your input. The point is to perform the extraction first, and then check if succeeded. If you do the former, you'll almost always get the problems you are experiencing.
The first extraction into n obtained 4 from the stream. After it found the newline it stopped and you printed the value of n. When the second loop executed, the extractor cleared the leading whitespace from the stream (meaning the newline after 4), found the end of the stream and set eofbit. Since no characters were extracted, it also set failbit. When you attempted to print the value again, all you were seeing was the result of the previous input operation.
This isn't the right way to perform a read. You have to do it before checking the stream. This is how it is commonly done:
while (in >> n)
{
std::cout << n << std::endl;
}
After the read is performed, operator bool() will be invoked on the stream, which will access its stream state and determine if the extraction succeeded. If it did, only then will the loop body execute.
You aren't checking the state of the operation. Even if in >> n; sets a status of fail (so n was not set to a new value), you perform the next line. See http://www.cplusplus.com/doc/tutorial/files/ or http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ or similar. Your file has an empty line before the eof, so you run the code in the while loop twice.
Here's what happens during the above code execution:
1st loop iteration:
read 4 into n
output n (4)
2nd loop iteration:
read EOF
(here there is no test for EOF)
output n (4)
3rd loop iteration (doesn't happen, because EOF was read during the last read)
You should be testing the state of in in your loop condition:
while (in >> n)
{
// all is good, carry on
}