CS253: Software Development with C++

Spring 2022

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 do something (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" << flush;  // Force writing now, not later.
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:
cin.clear(ios::failbit);
// I want to set failbit=1, and leave the other bits unchanged.
cin.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
165816.15 1966036.63

The .fail() method is sometimes misused:

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

if (in.fail())  // 🦡
    cerr << "failure!\n";
Read a number: 165816
Read a number: 1.96604e+06
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

$ cat /proc/uptime
165816.16 1966036.70

Use boolean context instead of .is_open() or .fail(). For error checking, use the technique described at the end of the Introduction to I/O Streams lecture.

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

int v;
while (v=1, in >> v)
    cout << "Read a number: " << v << '\n';

// All done reading.  Why did we stop?
// Bad data will set the variable to ±∞ or zero.
if (v != 1)
    cerr << "Bad data!\n";
Read a number: 165816
Bad data!