what does testing an "stream >> char" do? - c++

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.

Related

What does cin >> x evaluate to, on error?

Consider this snippet:
int a;
while (cin >> a){/* do something */}
On running this code, suppose I enter a string. The loop is exited. But then, since the expression inside while ends in error, and it doesn't evaluate to a bool type (is this incorrect thinking?), how does the compiler know to exit the loop?
cin >> x returns cin to allow chaining.
And in an boolean context, cin evaluates to true if and only if the last operation was successful.
Long story short, the loop will end on the first end of file or error.
cin >> a will always return a reference to cin.
The std::basic_ios base class has an explicit operator bool() that will be invoked when cin is "evaluated" in the condition of if, while, or for. When the operation fails, then failbit is set in the flags and the next time cin is converted to bool, the result is false because of the flag.
When you do
cin >> a
You call the basic_istream& operator>>( int& value ); and as you can see it returns basic_istream& so basically you have
while(cin)
and what that does is call
explicit operator bool() const;
which will return true if the stream is not in an error state and false if it is in an eror state. That is why the loop ends when there is an error.
The condition in while (cin >> a) is not when a != 0, but when std::cin is valid.
std::cin becomes invalid if you input string instead of int or if stream ends for example.
The class std::basic_ios, the base class of the class std::istream, has the conversion operator
explicit operator bool() const;
that returns true if the condition !fail().is true.
So if an error occurs in this statement
cin >> a
that returns the stream std::cin itself then it is contextually converted to the type bool with the value false and this loop
while (cin >> a){/* do something */}
does not execute its sub-statement.

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.

what does if(! (is >> s)) mean?

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

How does cin evaluate to true when inside an if statement?

I thought that:
if (true)
{execute this statement}
So how does if (std::cin >> X) execute as true when there is nothing "true" about it? I could understand if it was if ( x <= y) or if ( y [operator] x ), but what kind of logic is "istream = true?".
The answer depends on the version of the standard C++ library:
Prior to C++11 the conversion inside if relied on converting the stream to void* using operator void*
Starting with C++11 the conversion relies on operator bool of std::istream
Note that std::cin >> X is not only a statement, but also an expression. It returns std::cin. This behavior is required for "chained" input, e.g. std::cin >> X >> Y >> Z. The same behavior comes in handy when you place input inside an if: the resultant stream gets passed to operator bool or operator void*, so a boolean value gets fed to the conditional.
std::cin is of type std::basic_istream which inherits from std::basic_ios, which has an operator : std::basic_ios::operator bool which is called when used in if statement.
if(x) is equivalent to if(bool(x))
in this case bool(x) calls std::istream::operator bool(x)
this will return:
true if none of failbit or badbit is set.
false otherwise.
What is inside if condition will be evaluated to bool.
if(cin >> X) means that if condition is true, something was read to X; if condition is false, something else happened (e.g. stream ended) and X is not changed.
E.g. to read until the end of stream, you can use while(cin >> X).

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.