Post

C++ Streams

What is stream?: Serial IO Interferface to external devices (file, stdin/stdout, network, etc.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
string s("Hello");
s[3] = 't'; // Random access
//cout[3] = 't'; // Error

{
ofstream of("MyLog.txt"); // Creates a new file for write, if the file didn't exist
of << "Text" << endl;
of << 234 <<endl;
of << 2.3 <<endl; 

of << bitset<8>(14) << endl; // 00001110
of << complex<int>(2,3) << endl; // (2,3)

} //RAII

IO Operations:

formatting the data <——–> communicatiing the data with external devices

Software Engineer Principle: Low Couping -> Resuability

Ouput:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    ofstream of("Log.txt");// Open file for write , and clear the file
    cout<< "Text to the file"<< endl;
}

{
    ofstream of("Log.txt", ofstream::app); // Move the output pointer to te end of the file
    cout<< "Text to the file"<< endl;
}
{
    ofstream of("Log.txt", ofstream::in | ofstream::out);
    of.seekp(10, ios::beg); // Move the output pointer 10 chars after begin
    of << "12345"; // Overwrite 5 char
    of.seekp(-5, ios::end); //Move the output  pointer 5 chars before end
    of << "More text, more text" << endl;
    of.seekp(-5, ios::cur); // Move the ouput pointer 5 char before the current position
}

Input:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
    ifstream inf("Log.txt");
    int i;
    inf >> i; // read one word
    // Error status: goodbit, badbit, failbit, eofbit
    inf.good(); // Everything is OK (goodbit = 1)
    inf.bad(); //Non-recoverable error (badbit = 1)
    inf.fail(); //Failed Stream operation (failbit == 1 badbit == 1)
    inf.eof(); // End of file (eofbit == 1)

    inf.clear(); // Clear all error status
    inf.clear(ios::badbit); // sets a new value to the error flag

    inf.rdstate(); // Read the current status flag
    inf.clear(inf.rdstate() & ~ios::failbit); // Clear only the failbit

    if(inf) // Equivalent to: if (!inf.fail())
        cout << "Read successfully"
    
    if(inf >> i)
        cout << "Read successfully";

    // Handle the errors with exceptions
    inf.exceptions(ios::badbit | ios::failbit); // setting the exception mask
    // When badbit or failbit set 1, exception of iosLLfailure will be thrown
    // When eofbit set to 1, no exception 
    inf.exceptions(ios::goodbit); // No exception

}

Formatting IO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    
    cout << 34 << endl; //34
    cout.setf(ios::oct, ios::basefield);//ocatal
    cout << 34; // 42
    cout.setf(ios::showbase);
    cout << 34; // 042
    cout.setf(ios::hex, ios::basefield);
    cout <<34; // 0x22

    cout.unsetf(ios::showbase);
    cout << 34; // 22

    cout.setf(ios::dec, ios::basefield);

    cout.width(10);
    cout << 26 << endl; //          26
    cout.setf(ios::left, ios::adjustfield);  //26

    // Floating points values
    cout.setf(ios::scientific, ios::floatfield); 
    cout << 340.1 << endl; // 3.401000e+002
    cout.setf(ios::fixed, ios::floatfield);
    cout << 340.1 << endl; //340.100000
    cout.precision(3)l
    cout << 340.1 << endl; //340.100

    int i;
    cin.setf(ios::hex, ios::basefield); 
    cin >> in // Enter: 12
    //i==18

    ios::fmtflags f = cout.flags(); //Current flags been used
    cout.flags(ios::oct | ios::showbase);
    cout.flags(); // returns ios::oct | ios::showbase

Unformated IO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    ifstream inf("Log.txt");
    char buf[80];
    inf.get(buf,80); // read up to 80 chars and save to buf
    inf.getLine(buf, 80); //readu up to 80 or until a '\n'
    inf.read(buf, 80); // read 80 chars
    inf.ignore(3);
    inf.peek();
    inf.unget(); // return a char back to the stream( retuns same last char)
    inf.putback('z'); //returns a char 'z' to the stream
    inf.get();
    inf.gcount(); // return the number of  chars  being read  bu last unformatted read

    //output
    ofstream of("Log.txt");
    of.put('c');
    of.write(buf, 6); // write first 6 chars of buf
    of.flush(); // Flush output to screen in case of cout

Descriptions: In this video Bo Qian explains what are manipulators by using an example that is well know std::endl. A brief description concludes that endl is a fucntion that manipulates the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    ostream& endl(ostream& sm){ // Manipulator
        sm.put('\n');
        sm.flush();
        return sm;
    }

    ostream& ostream::operator<<(ostream& (*func)(ostream&)){
        return (*func)(*this);
    }

    int main(){
        cout << "hello" << endl; //endl: '\n' and flush
        // object? Build-in data type? function? (look to func above)

        // More manipulators
        cout << ends; //'\0'
        cout << flush;
        cin >> ws; // read and discard white spaces
        cout << setw(8) << left << setfill('_') << 99 << endl; //99______
        cout << hex << showbase << 14; //0xe
        
        // More in: https://www.cplusplus.com/reference/ios/
    }

IO Operations:

  • Formating data – stream
  • Communicating data to external devices – stream buffer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    cout << 34; //Formatting
    streambuf* pbuf = cout.rdbuf();

    ostream myCout(pbuf);
    myCout.setf(ios::showpos);
    myCout.width(20);
    myCout << 12 << endl; //        +12
    cout << 12 << endl; //12
    
    //Redirecting
    ofstream of("Log.txt");
    streambuf* oriBuf = cout.rdbuf(); // saving backup from original
    cout.rdbuf(of.rdbuf());
    cout << "Hello" << endl; // Log.txt has "Hello"

    cout.rdbuf(oriBuf); // setting cout to original buffer

    cout << "Bye" << endl; //stdout: Bye

    //Stream buffer iterator
    istreambuf_iterator<char> i(cin);
    ostreambuf_iterator<char> o(cout);

    // Copy
    while(*i != 'x'){
        *o = *i;
        ++o;
        ++i;
    } // exit option if press x

    //Similar to copy with no exit
    copy(istreambuf_iterator<char>(cin), istreambuf_iterator<char>(), ostreambuf_iterator<char>(cout));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    // Srtring Stream
    stringstream ss; // Stream without IO operation
    // read/write of string
    // Example
    ss << 89 << " Hex: " << hex << 89 << " Oct: " << oct << 89;
    cout << ss.str() << endl; //89 Hex: 59 Oct: 131

    int a, b, c;
    string s1;

    ss << hex >> a; // Formatted input works token by token, spaces, tabs, newlines
        //a == 137
    ss >> s1; // s1: "Hex:"
    ss >> dec >> b; //b==59
    
    ss.ignore(6);

    ss>> oct >> c; //c==89

Recommendation: stringstream is used in the example above for input and output but this fucntionality is also offered by two other stream class.

  • ostringstream: Used only for formatted output
  • istringstream: Used only for formatted input

It is recommended for readibility that we use the streams mention above, because they portray our intention for the given stream.

Description: Class of Dog allows for IO Stream creating and outputing formatted data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    using namespace std;

    //Creating Stream-enabled Class
    struct Dog{
        int age_;
        string name_;
    };

    // Input Stream
    ostream& operator<<(ostream& sm, const Dog& d){
        sm << "My name is " << d.name_ << " and my age is " << d.age_ << endl;
        return sm; 
    }

    // Output Stream
    istream& operator>>(istream& sm, Dog& d){
        sm >> d.age_;
        sm >> d.name_;
        return sm;
    }

    int main(){
        Dog d{2, "Bob"}; // Universal Initialization from c++11
        cout << d;

        cin >> d; // 5 carl [Input]
        cin << d; //My name is carl and my age is 5 [Output]
    }

This post is licensed under CC BY 4.0 by the author.