Ежедневный бит(е) C++ #249. Обработка ошибок в стандартной библиотеке iostreams.

Несмотря на недавние разработки (‹format>< и ‹print><), iostreams останется с нами в обозримом будущем.

Одной из особенностей iostreams является их подход к обработке ошибок, при котором ошибки представляются с помощью флагов и состояний ошибок.

#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>

// A stream that isn't associated with any file yet.
std::fstream f;
// f.good() == true, (bool)f == true

// Trying to write into a closed stream.
f << 10;
// f.good() == false, f.fail() == true, f.bad() == true
// (f.rdstate() & std::ios_base::badbit) != 0

// Badbit represents an irrecoverable error,
// i.e. the stream is in a bad state.


// Reset the stream by opening /dev/null.
// Reading from /dev/null immediately leads to EOF
f.open("/dev/null");
// f.good() == true

f.peek(); // Don't even read, just peek at the next character.
// f.good() == false, f.eof() == true
// (f.rdstate() & std::ios_base::eofbit) != 0

// Eofbit represents a stream that is at the end of file.


std::stringstream s("hello");
// Try to parse an integer from a string 
// that contains non-digit characters.
int v;
s >> v;
// s.good() == false, s.fail() == true
// (s.rdstate() & std::ios_base::failbit) != 0

// Failbit represents recoverable errors, mostly parsing errors.

std::string txt;
// A stream not in a good state will not proceed
// with further insertion/extraction.
s >> txt;
// txt == ""

s.clear(); // clear error bits
s >> txt;
// txt == "hello"


// Exceptions can be opted into, however, 
// they do not contain useful information.
try {
    // s is currently at eof, opting into exceptions 
    // will therefore throw immediately
    s.exceptions(std::ifstream::eofbit); // the argument is a bitmask
} catch(const std::exception& e) {
    std::cout << e.what() << "\n";
   // basic_ios::clear: iostream error
}

Откройте пример в Compiler Explorer.