CS253: Software Development with C++

Fall 2021

Ios State Flags

Show Lecture.IosStateFlags as a slide show.

CS253 Ios State Flags

Overview

ios State Flags

Summary of flags

ios::eofbit

ifstream in("/dev/null");
char c;
in.get(c);
if (in.rdstate() & ios::eofbit)  cout << "After, eofbit\n";
if (in.rdstate() & ios::failbit) cout << "After, failbit\n";
if (in.rdstate() & ios::badbit)  cout << "After, badbit\n";
After, eofbit
After, failbit

eofbit ≡ hit eof trying to read; failbit ≡ tried to get a char and couldn’t.

ios::failbit

ifstream in("/etc/hostname");
float f;
in >> f;
if (in.rdstate() & ios::eofbit)  cout << "After, eofbit\n";
if (in.rdstate() & ios::failbit) cout << "After, failbit\n";
if (in.rdstate() & ios::badbit)  cout << "After, badbit\n";
After, failbit

ios::failbit upon open failure

Also, ios::failbit is set when a file can’t be opened.

ifstream in("/this/file/doesn’t/exist");
if (in.rdstate() & ios::eofbit)  cout << "eofbit\n";
if (in.rdstate() & ios::failbit) cout << "failbit\n";
if (in.rdstate() & ios::badbit)  cout << "badbit\n";
failbit

ios::badbit

ofstream out("/dev/full");
out << "foo" << endl;
if (out.rdstate() & ios::eofbit)  cout << "After, eofbit\n";
if (out.rdstate() & ios::failbit) cout << "After, failbit\n";
if (out.rdstate() & ios::badbit)  cout << "After, badbit\n";
After, badbit

The bits are sticky

ifstream in("/etc/hostname");
double d;
in >> d;
if (in.rdstate() & ios::failbit) cout << "#1: failbit\n";
char c;
in >> c;
if (in.rdstate() & ios::failbit) cout << "#2: failbit\n";
#1: failbit
#2: failbit

Clearing bits

ifstream in("/etc/hostname");
double d;
in >> d;
if (in.rdstate() & ios::failbit) cout << "#1: failbit\n";
char c;
in >> c;
if (in.rdstate() & ios::failbit) cout << "#2: failbit\n";
in.clear();
in >> c;
if (in.rdstate() & ios::failbit) cout << "#3: failbit\n";
cout << "c=‘" << c << "’\n";
#1: failbit
#2: failbit
c=‘b’

ios::clear() clears ios::badbit, ios::eofbit, and ios::failbit.

Setting bits

// I want to set failbit=1, eofbit=0, badbit=0:
in.clear(ios::failbit);
// I want to set failbit=1, and leave the other bits unchanged.
in.setstate(ios::failbit);

Interrogating bits

The previous slides have been interrogating the bits in a straightforward, but clumsy fashion. There are several other ways:

HowResults
stream.rdstate()ios::eofbit|ios::badbit|ios::failbit
stream.good()no bits are set
stream.eof()ios::eofbit is set
stream.bad()ios::badbit is set
stream.fail()ios::badbit or ios::failbit is set 😲 🤯
! stream.fail()
stream in boolean context !.fail()

Use of fail()

$ cat /proc/uptime
1761245.62 20834190.52

The fail() method is sometimes misused:

ifstream in("/proc/uptime");
for (float f; in >> f; )
    cout << f << '\n';

if (in.fail())
    cerr << "failure!\n";
1.76125e+06
2.08342e+07
failure!
Why did it fail?

Because the final read in the loop failed. If no reads in the loop failed, then we’d still be in the loop. So, this call to fail() always succeeds—not useful.

Advice

Use boolean context instead of is_open() or fail(). Only use eof() for error-checking after the loop.

ifstream in("/etc/hostname");
if (!in) {
    cerr << "Can’t open /etc/hostname for reading\n";
    return 1;
}

for (float f; in >> f; )
    cout << "Hooray, got a number: " << f << '\n';

// All done reading.  Why did we stop?
// Was it end-of-file, or did something go wrong?
// Don’t check .fail(); that’ll always be true.
if (!in.eof())
    cerr << "Bad numbers!\n";
Bad numbers!