istream& Read(istream &is)
{
std::string buf;
while (is >> buf)
{
cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
cout << is.rdstate() << endl;
cout << buf << endl;
}
cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
cout << is.rdstate() << endl;
is.clear();
cout << is.eofbit << " " << is.failbit << " " << is.badbit << endl;
cout << is.rdstate() << endl;
return is;
}
If I input normal characters like "test",the output is 1 2 4 0
.
Then I type CTRL+Z (windows),the output is 1 2 4 3
1 2 4 0
.
Question :
1. what does rdstate()
return value means? (Why does it output 3,not 2? not 1?)
is.eofbit
and is.failbit
change after I typed CTRL+Z ? (As C++ Primer 5th Editon says,Reaching end-of-file sets both eofbit and failbit ) The rdstate () method of ios class in C++ is used to read the internal state of this stream. Parameters: This method does not accept any parameter. Return Value: This method returns the current internal state of this stream.
This syntax is used in function just as a jump statement in order to break the flow of the function and jump out of it. One can think of it as an alternative to “ break statement ” to use in functions. But if the return statement tries to return a value in a void return type function, that will lead to errors.
As soon as the statement is executed, the flow of the program stops immediately and return the control from where it was called. The return statement may or may not return anything for a void function, but for a non-void function, a return value is must be returned. Take a step-up from those "Hello World" programs.
Return statements come in many shapes. The following syntaxes are most common: in C and C++, undefined behavior if function is value-returning In some assembly languages, for example that for the MOS Technology 6502, the mnemonic "RTS" (ReTurn from Subroutine) is used.
The member std::ios::rdstate()
simply returns a combination of the state flags std::ios_base::badbit
, std::ios_base::eofbit
, and std::ios_base::failbit
. Under which conditions which bits gets set isn't entirely consistent but the intent is the following:
std::ios_base::badbit
gets set when the stream is in genuinely dysfunctional state and you [probably] won't get anything out of it. For example, this flag is set if there is no stream buffer or when any of the operations on the stream has thrown an exception.std::ios_base::failbit
gets set when an input operation failed, e.g., because a formatted input operation got an unexpected characters. It may be possible to recover from this error by clearing it, ignoring a few characters, and trying again.std::ios_base::eofbit
gets set when [the current] EOF is reached, i.e., when there could be no more characters extracted for now.Now, in your case you entered a string and reading it was successful, i.e., there are no flags set. Note that reading stopped with the newline character, i.e., you really entered "test\n"
and the stream extracted these five characters. When you then ended the stream, the stream reached EOF while trying to read a string, i.e., it set std::ios_base::eofbit
and the input failed also setting std::ios_base::failbit
.
If you want to see only std::ios_base::eofbit
set, you can do so by using a stream which ends with a word right at the end of the stream without any following space character. An easy way to get such a stream is to use an std::istringstream
and read from that:
std::istringstream in("test");
Read(in);
Another easy set up is to see std::ios_base::badbit
set: you'd just create a stream without a stream buffer, e.g.:
std::istream in(0);
Read(in);
Note that the stream will initially have std::ios_base::badbit
set and also get std::ios_base::failbit
set upon an attempt to read a character. After clear()
ing the std::ios_base::badbit
will still be set, though.
To get std::ios_base::failbit
set without also having std::ios_base::eofbit
set you'll need to prevent it from seeing a non-whitespace character: the input operator for std::string
by default start off skipping whitespace and then reads until it either reaches whitespace or EOF and it is successful if it could read at least one non-whitespace character. An approach to do that is to turn automatic skipping of whitespace off, e.g.:
std::istringstream in("test test");
Read(in >> std::noskipws);
BTW, note that there is no guarantee for the values of std::ios_base::eofbit
, std::ios_base::failbit
, or std::ios_base::badbit
other than they can be used as bitmasks in some form.
The member std::ios::rdstate()
simply returns a combination of the state flags std::ios_base::badbit
, std::ios_base::eofbit
, and std::ios_base::failbit
.But the size of each state flag is not 1 bit, the type of all three state flags are enum std::_Iosb<int>::_Iostate
, which is machine-dependent integral as well as std::strm::iostate
. On my machine, they account for 4 bytes.
But I don't understand what its output means
when only badbit
gets set explicity or directly, the value of s.rdstate()
is 4.
when only failbit
gets set explicity or directly, the value of s.rdstate()
is 2.
when only eofbit
gets set explicity or directly, the value of s.rdstate()
is 1.
when several parts of them get set explicity or directly, the value of s.rdstate()
can calculated from the sum of the corresponding value, namely, the 1st bit of s.rdstate()
indicates the state ofeofbit
,the 2nd bit of s.rdstate()
indicates the state offailbit
,the 3th bit of s.rdstate()
indicates the state ofbadbit
.
But the interesting thing is when the badbit
gets set explicitly or directly, the failbit
will get set in response(not explicity or directly).At this time, the value of s.rdstate()
do not count failbit
in. Read my code and see the output, you will understand what I mean.
#include<iostream>
#include<istream>
std::istream & print(std::istream &is) {
static unsigned cnt = 0;
++cnt;
std::cout << cnt << ((cnt % 10 == 1) ? "st" :
(cnt % 10 == 2) ? "nd" : "th")
<< " call print" << "\n";
std::cout<< "is.badbit: " << is.badbit << "\n"
<< "is.failbit: " << is.failbit << "\n"
<< "is.eofbit: " << is.eofbit << "\n"
<< "is.bad(): " << is.bad() << "\n"
<< "is.fail(): " << is.fail() << "\n"
<< "is.eof(): " << is.eof() << "\n"
<< "is.rdstate(): " << is.rdstate() << "\n";
return is;
}
using std::cin;
using std::cout;
using std::endl;
using std::vector;
int main()
{
cout << "sizeof(iostate): " <<sizeof(std::istream::iostate)<<"\n";
cout << "sizeof(goodbit): " << sizeof(std::istream::goodbit) << "\n";
cout << typeid(std::istream::goodbit).name();
cout << endl;
print(cin);
cout << endl;
cin.setstate(std::istream:: badbit);
print(cin);
cout << endl;
cin.clear();
cin.setstate(std::istream::failbit);
print(cin);
cout << endl;
cin.clear();
cin.setstate(std::istream::eofbit);
print(cin);
cout << endl;
cin.clear();
cin.setstate(std::istream::badbit);
cin.setstate(std::istream::failbit);
print(cin);
cout << endl;
cin.clear();
cin.setstate(std::istream::badbit);
cin.setstate(std::istream::eofbit);
print(cin);
cout << endl;
cin.clear();
cin.setstate(std::istream::failbit);
cin.setstate(std::istream::eofbit);
print(cin);
cout << endl;
}
The output is:
sizeof(iostate): 4
sizeof(goodbit): 4
1st call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 0
is.eof(): 0
is.rdstate(): 0
2nd call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 0
is.rdstate(): 4
3th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 1
is.eof(): 0
is.rdstate(): 2
4th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 0
is.eof(): 1
is.rdstate(): 1
5th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 0
is.rdstate(): 6
6th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 1
is.fail(): 1
is.eof(): 1
is.rdstate(): 5
7th call print
is.badbit: 4
is.failbit: 2
is.eofbit: 1
is.bad(): 0
is.fail(): 1
is.eof(): 1
is.rdstate(): 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With