Digital Garden
Computer Science
C++
Stream I/O

Stream I/O

Standard I/O

In C the standard input and output work with the functions scanf() and printf().

In C++ this works over byte streams which are objects of the class istream for input and ostream for output.

The objects cin and cout are such objects and are most commonly used. There are however also cerr for the standard error output and clog for buffered standard error output.

Un/Formatted I/O

Formatted I/O uses the << and >> operators. These operators either read an object and write it to a stream as a string or the opposite way around. Unformatted uses like in C the write() and read() functions.

#include<iostream>
using namespace std;
int main() {
    constexpr int nColumns = 4;
    cout << "ASCII-Tabelle" << endl << endl;
    for (int i = 32; i < 128; i++) {
        cout.width(3); // Numberwidth: 3
        cout.fill('0'); // fill with leading zeros
        cout << i << " = 0x";
        cout.setf(ios::hex, ios::basefield); // set to base 16
        cout.setf(ios::uppercase); // Hexnumbers in CAPS
        cout << i << ": ";
        cout.unsetf(ios::hex); // change back to decimal
        cout << (char)i << '\t'; // output char
        if (i % nColumns == nColumns - 1)
            cout << endl;
    }
}

Formatted input of booleans:

cin.setf(ios::boolalpha);
cin >> boolValue;

Error handling of formatted input:

if(cin.good()) { // short: if (cin)
    cout << "Input is: " << i << endl;
} else{
    cin.clear();
    getline(cin, s); // read entire line
    stringstream ss(s);
    cout << "No number was entered instead the strings: ";
    while(ss.good()) {
        ss >> s;
        cout << "[" << s << "]";
    }
    cout << endl;
}

Stream Manipulators

Manipulators are helper functions to control formatted input/output streams to make life easier then before with the multiple flags etc.

// before
cout.setf(ios::hex, ios::basefield);
cout.setf(ios::uppercase);
cout << i << endl;
// after
cout << hex << uppercase << i << endl;

These are all pointers to functions. For example, the implementation of endl looks something like this:

ostream& endl(ostream& os){
    os.put('\n');
    os.flush();
    return os;
}

Some of the important manipulators are:

  • setw(int i) is used to set the field width in output operations.
  • setfill(char c) is used to fill the character ‘c’ on output stream.
  • setprecision(int i) sets val as the new value for the precision of floating-point values.
  • setbase(int i) is used to set the numeric base value for numeric values.
  • showpos forces to show a positive sign on positive numbers.
  • noshowpos forces not to write a positive sign on positive numbers.
  • showbase indicates the numeric base of numeric values.
  • uppercase forces uppercase letters for numeric values.
  • nouppercase forces lowercase letters for numeric values.
  • fixed uses decimal notation for floating-point values.
  • scientific uses scientific floating-point notation.
  • hex read and write hexadecimal values for integers and it works same as the setbase(16).
  • dec read and write decimal values for integers i.e. setbase(10).
  • oct read and write octal values for integers i.e. setbase(10).
  • left adjusts output to the left.
  • right adjusts output to the right.

C++ Stream Classes

Just like in Java there are lots of different streams all with there pros and cons etc.

Hierarchy of all the streaming classes in C++.

Stream States

You can read the state (a number, iostate) of a stream with rdstate(). 0 means everything is good, all other numbers mean something different and depending on which of the 3 bits are set something different. eofbit means the end of the file has been reached, failbit a logical error has happend like an int should be read but "hello" was input (EOF also sets this bit). badbit means something went wrong when reading or writing for example hardware or OS issue.

Explanation of the different states of a stream in C++ and how they are set.

File I/O

Text Files

Unformatted

Very C-like.

  • peek() returns the next character in the stream or EOF.
  • get() returns a character from the stream.
  • read(char* s, streamsize n) reads n characters from the stream.
  • getting(istream& is, string& str) reads characters from stream and stores them into str until a newline.
  • ignore() reads and discards a character.
  • gcount() returns the number of characters extracted by the last unformatted input operation performed on the object.
  • unget() Attempts to make the last character extracted from the stream once again available.
  • put() writes a character.
  • write() writes n characters.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void main(){
    ifstream inData;
    string fileName;
    cout << "Enter the file name: ";
    cin >> fileName;
    inData.open(fileName, ios::in); // open file
    if( !inData ) {
        cerr << "Couldn't open file!" << endl;
    } else {
        while(!inData.eof()) {
            cout << static_cast<char>(inData.get()); // read char for char.
        }
        inData.close(); // close file
    }
}

Formatted

#include<fstream>
#include<iostream>
 
using namespace std;
int main() {
    // Create file
    fstream inOutFile("fstream.txt", ios::out | ios::trunc);
    inOutFile.close();
 
    // open for read and write
    inOutFile.open("fstream.txt", ios::in | ios::out);
 
    // write
    for(int j = 1; j <= 20; ++j)
        inOutFile<< j << ' ';
    inOutFile<< endl;
    // jump to start
    inOutFile.seekg(0);
    // read
    int i;
    while(inOutFile >> i) {
        cout << i << ' ';
    }
    inOutFile.clear(); // remove EOF status
    inOutFile.seekg(25); // jump to position 25
 
    while(inOutFile.get() != ' '); // go to start again
 
    while(inOutFile>> i) {
        cout << i << ' ';
    }
}

Binary Files

#include<iostream>
#include<iomanip>
#include<fstream>
#include<sstream>
#include<string>
 
using namespace std;
 
struct S {
    int value;
    string text;
};
 
int main() {
    constexpr int size= 10;
    S array[size];
    ofstream ofs;
    // Array init
    for(int i = 0; i < size; i++) {
        stringstream strs;
        array[i].value= i;
        strs << setw(2) << setfill('0') << (i+1) << "._Array-Element";
        strs >> array[i].text;
    }
    // open file
    ofs.open("ouput.dat", ios::out | ios::binary);
    if(!ofs) {
        cerr << "Couldn't open file!" << endl;
        return 1;
    }
    // write array to file, tricky
    ofs.write((char*) array, size * sizeof(S));
    ofs.close();
    // open input
    ifstream ifs;
    ifs.open("ouput.dat", ios::in | ios::binary);
    if(! ifs) {
        cerr << "Couldn't open file!" << endl;
        return 1;
    }
    // read element by element
    for(S& s: array) {
        ifs.read((char*)&s, sizeof(S));
        cout<< s.text<< " = " << s.value<< endl;
    }
    ifs.close();
}