what does if(! (is >> s)) mean? - c++

Here is an overloaded >>operator function:
std::istream& operator>>(std::istream& is, std::vector<int>& v){
string s;
if (! (is >> s) )
return is;
...
return is;
}
To my understanding, if(! (is >> s)) make no sense because the terminal or console will wait until the input from keyboards or other sources enter s. So value of condition in if() will ultimately be false. Who can help?

The is >> s attempts to read the string s from stream is.
istreams operator>>() returns a reference to is.
istreams operator!() tests if the stream is in an invalid state. Specifically, it returns true if the stream's badbit or failbit has been set.
So,
if (! (is >> s) )
return is;
is functionally equivalent to
is >> s;
if (is.fail()) return is; // is.fail() returns true if failbit or badbit are set
which means that the function immediately returns if reading a string from the stream fails. Note that this is distinct from reaching the end of the stream.

istream does not have to be a console. It can be a stringstream. And besides, the 'waiting for user input' is not seen by the application code. It is asleep while the input stream is being filled (by the operating system, underlying library, ...)
Anyhow: in case the input stream contains no data at all, this condition will be true.
std::string s; // empty!
std::stringstream ss(s);
std::vector<std::string> strings;
ss >> strings; // should be empty!

To understand what if (!(is >> s)) means you need to understand what if (is >> s) means.
Since is is an std::istream, operator >> returns an std::istream. Hence, is >> s is an std::istream, which inside an if must produce a logical value true or false. This Q&A explains how it is done in different versions of C++. Essentially, std::istream evaluates to a true condition when the operation is successful.
Now that you know the meaning of is >> s, you can figure out that adding a negation flips that meaning: !(is >> s) would be true only when reading an s from is is unsuccessful. For strings an unsuccessful read means that the stream is in an invalid state, for example, because the end of stream has been reached.

you are doing many things in one line
! (is >> s)
you take the inputstream and use it to assign the object s, the evaluate teh result of s in the if condition

Related

what does testing an "stream >> char" do?

I have this snippet of code, which has the purpose of defining the >> operator for a struct point (it's not the whole function, just the beginning).
struct Point {
int x;
int y;
};
The code snippet
istream& operator>>(istream& is, Cord::Point& p) {
char ch1;
if (is >> ch1 && ch1 != '(') { // Is this not a point?
is.unget();
is.clear(ios_base::failbit);
return is;
}
//More code...
}
should function by checking if the input if the first character is ( essentially checking if it should proceed in assuming this point is the form of (x, y). I understand what the
ch1 == '(' is doing but what is the purpose of is >> ch1. It must be a boolean, but it seems to always be false because this check always fails from my testing.
what does testing an “stream >> char” [is >> ch1] do?
>> is the stream extraction operator. Given a character operand, it extracts a single character from the stream, and assuming no error occurs, assigns the value to the operand.
It must be a boolean
The stream extraction operator returns the stream. The stream converts implicitly to bool. The converted value is true if the stream has no errors and is ready for I/O operations and false otherwise.

while (cin>> struct str) in c++ how can I use?

I'm having a trouble when I use while(cin) with struct. Would someone please make me clear about this problem? I don't know whether this kind of post was asked or not. If it was please forgive me and my bad english as well.
struct ThiSinh{
string m_HT;
float m_H;
};
I overload operator >> for it
bool operator >> (istream& is, ThiSinh &ts){
getline(is, ts.m_HT);
is >> ts.m_H;
is.ignore();
return ???;
}
Because while (cin >> ThiSinh) require a bool type, so I dont know what number or data it should return. And how to break the while loop when I press ctrl + Z.
I have also tried
while(cin){
ThiSinh ts;
cin >> ts;
}
and it worked but I dont want to get that false data. So someone please helps me out. Thanks in advance.
Your operator >> returns a bool, which is extremely unusual for a stream extraction operator, and renders it unusuable in most streaming contexts. Such operators are expected to return a reference to the stream on which they operate:
istream& operator >> (istream& is, ThiSinh &ts){
getline(is, ts.m_HT);
is >> ts.m_H;
is.ignore();
return is;
}
This is how multiple exrtactions actually work:
std::cin >> a >> b >> c;
Effectively, this first does auto &tmp = operator>>(std::cin, a), and then calls operator>>(tmp, b), and so on.
The reason why streams (and by extension, stream extraction operations) can be used in conditionals is that std::istream (and std::ostream) defines a conversion to bool (which returns true iff the stream is in error-free state); that conversion is then invoked by the conditional.
In other words, this:
while (std::cin >> ts)
effectively becomes this:
while (static_cast<bool>(operator>>(std::cin, ts)))
and the cast is possible because operator>> returns std::istream& and std::istream defines a conversion to bool.

How is "std::cin>>value" evaluated in a while loop?

Currently I'm self-learning C++ Primer 5th. Here comes something I'm not sure. (I couldn't find the exact relevant question on F.A.Q).
Consider this while loop:
while(std::cin>>value){...} \\value here was defined as int.
The text book says:
That expression reads the next number from the standard input and stores that number in value. The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. This condition, therefore, tests std::cin.When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.
My question is: does std::cin read input into value first then test the validation of std::cin, or test std::cin first then decide whether to read into 'value'? I'm quite confused about when it "returns its left operand".
Remember that your code is equivalent to:
while (std::cin.operator>>(value)) { }
Or:
while (1) {
std::cin >> value ;
if (!std::cin) break ;
}
The "code" always tries to read from std::cin into value before testing std::cin.
Let's look at the quote:
[...] The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. [...]
This only means that std::cin.operator>>(value) return std::cin.
This condition, therefore, tests std::cin. When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.
What the text book says is that after trying to read an integer from std::cin to value, the >> operator returns std::cin. If std::cin is in a good state after reading value, then the test passes, otherwize it fails.
Some extra details:
When you do std::cin >> value, you basically call istream::operator>>(int&), and yes there is a test inside that method: If the test passes, then the internal state of std::cin is set to ios_base::goodbit, if it fails, internal state is set to on of the error flag (eofbit, failbit or badbit).
Depending on the exception mask for std::cin, if the internal test fails, an exception may be thrown.
From your quote:
When we use an istream as a condition, the effect is to test the state of the stream.
This basically mean that:
if (std::cin) { }
Is equivalent to:
if (!std::cin.fail()) { }
And std::cin.fail() check for failbit or badbit. This means that while (std::cin >> value) { } does not test the eofbit flag and will only fail when the input cannot be converted to an integer value.
does std::cin read input into value first then test the validation of
std::cin, or test std::cin first then decide whether to read into
'value'
cin first tries to read an int from the standard input, if cin is in a good state: if it fails to, it will set the stream to a bad state; regardless of the operation done, it will return the stream itself (i.e. the "left operand" -- cin), that will allow you to check for success or failure.
If you wanted to explicitly test the validity of the stream first and only then try to read the value, you would have:
while (cin && cin >> value)
but it's pretty redundant, since, as I've told you, cin will not even try to read value if it's already in a bad state.
There are two tests.
The first test is the condition of the while statement
while(std::cin>>value){...}
This condition tests the result of calling operator function operator >>
The second test is a condition within the operator. If the state of the stream std::cin is good then the function tries to read an integer from the string. Otherwise it returns std::cin with the current erroneous state of std::cin.
In the while condition there is an expression
std::cin>>value
This expression must be evaluated. So this condition tests the result of the call of operator >> .
The result of the operator is the stream std::cin But it can be contextually converted to a bool value due to operator
explicit operator bool() const;
which returns the state of the stream
!fail().
I assume your "value" is for example an int
The stream tries to read input until the next whitespace.
if eof is found ... -> then the state will be set to "eof", >> will return the stream and the boolean evaluation of the stream will return false
if an error (I/O for example) happens during the reading process, the state will be set to "bad", >> will return the stream and the boolean evaluation of the stream will return false
if whitespace has been found, then a conversion from the read characters to int (the above assumption) will be attempted. If it fails (because the read input is for example: "xx" and not a number) the state of the stream will be set to "fail". >> will return the stream and the boolean evaluation of the stream will return false
if we are so far down the chain, eof was not found, no IO error (or other) happened, and the characters -> int conversion was successful. >> will return the stream and the boolean evaluation of the stream will return true.
And your "value" will contain the appropriate value
Presumably you wouldn't have any confusion with a simple function call:
SomeReturnType some_function(int&);
while (some_function(value)) { ... }
The above code will repeatedly call some_function until the return value from the function call, interpreted as a boolean, is false. The function is called for each step in the loop. Whether the function changes the value of value is up to the function. It certainly can do so, and presumably will do so (but that's an issue for the designer of the function).
The loop while (std::cin>>value) {...} is completely equivalent to while (std::cin.operator>>(value)) {...}. This is just a function call to the member function std::stream::operator>>(int&).
The operator first reads the value and then returns a reference to the object. The while statement first calls that operator and second tests the returned value.

Why does while(std::ifstream >> s) work?

I've used statements such as this quite a bit in my C++ programming:
std::string s;
std::ifstream in("my_input.txt");
if(!in) {
std::cerr << "File not opened" << std::endl;
exit(1);
}
while(in >> s) {
// Do something with s
}
What I want to know is, why does this work?
I looked at the return value of operator>>, and it's an istream object, not a boolean. How does an istream object somehow get interpreted as a bool value that can be put inside of if statements and while loops?
The base class std::basic_ios provides an operator bool() method that returns a boolean representing the validity of the stream. For example, if a read reached the end of file without grabbing any characters, then std::ios_base::failbit will be set in the stream. Then operator bool() will be invoked, returning !fail(), at which time extraction will stop because the condition is false.
A conditional expression represents an explicit boolean conversion, so this:
while (in >> s)
is equivalent to this
while (static_cast<bool>(in >> s))
which is equivalent to this
while ((in >> s).operator bool())
which is equivalent to
while (!(in >> s).fail())
std::basic_ios, from which the input and output streams inherit, has the conversion function operator bool (or operator void* prior to C++11 to get around the safe-bool problem, which is no longer an issue thanks to the explicit keyword).
See std::basic_ios::operator bool:
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}. Such loops execute the loop's body only if the input operation succeeded.

How to stop reading using >> when there are no more word left

I am given a list of words in a text file, all seperated by newlines. Reading them using fstream and >>, and not knowing the amount of words there are. How do I tell the program when to stop? I've tested it out, and the value of the variable just stays the same of the last word read.
Checking the state of the stream after extraction is always a good idea. It tells you if there were any problems while performing the extraction, or whether the file stream has reached the end-of-file character (EOF).
The latter case is what you're dealing with. All you need to do is perform the extraction while the stream is in a good state, which is idiomatically done in the following way:
while (in >> str) {
// ...
}
After the stream performs the extraction, operator bool() is invoked, which calls !fail(). Using a while loop will allow the next extraction to be performed automatically. It will stop when the stream has performed an incorrect extraction, is perhaps out of memory, when it hits the EOF character, or some other user-defined situation.
You've failed the fundamental principle of I/O: You must check whether your input operation succeeds. You cannot know that in advance, you only learn that after you have tried:
for (std::string word; std::cin >> word; )
// ^^^^^^^^^^^^^^^^<----------- test for success
{
std::cout << "Here is one word: " << word << std::endl;
}
You have to remember that the input operator >> returns the stream it uses, and that streams can be used as boolean conditions. That means you can use it as a loop condition:
while (some_stream >> some_variable)
{
...
}