Stream input/output

Stream objects

In the C Standard Library, streams are represented by structure objects of type FILE. In C++, streams are objects of the class std::istream (For input only streams), std::ostream (For output only streams) and std::iostream (For input and output streams). To read and write from/to files, we do not directly use the classes listed before, but specialized classes that inherit from them. No matter if the streams are linked to a file or something else (Example, the console), the methods and operators used to input/output from/to them are the same.

The class std::ostream is defined in the header <ostream>. The classes std::istream and std::iostream, which is a class that inherits from both std::ostream and std::istream, are defined in the header file <istream>. Therefore, including the header <istream> automatically includes <ostream>.

The header <iostream> includes <istream> and defines the stream objects std::cout, std::cin, std::cerr (Like std::cout, but outputs to the error channel), and std::clog (Like std::cerr).

Stream operators

We already saw how to input/output from a stream using the stream operators (<< and >>).

With the input stream operator, when we input text from the console, the text is automatically converted into the type of the left operand (If it is not a type representing text). For example, if we read, with the >> operator, something into a variable of floating point primitive type, the inputted string is automatically converted into a floating point number.

Similarly, when we output a variable to the console using the output stream operator, the value of the variable is automatically converted into text (If it is not already text). For example, if we output, using the << operator, a floating point number with the value 82.56, it is automatically converted into the string "82.56", which is then written to the console.

The methods shown in that page does not convert values from/to text. They simply input/output bytes (Which may be interpreted as characters) from/to streams.

Method write

We can use the method std::ostream& std::ostream::write(const char* data, streamsize size) to output bytes to a stream. The first argument is a pointer to the bytes to output. The second one is the number of bytes to write. A reference to the stream the method is called from is returned. If we output bytes to the console, they will be interpreted as characters according to the ASCII table.

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
#include <iostream> int main() { char str[] = "Hello!\n"; /* The size of the array minus 1, because we do not want to output the null character. */ std::cout.write(str, sizeof(str)-1); // "Hello!" is printed into the console. /* We can do the following, because the method 'write' returns a reference to the object it is called from, which in this case is std::cout. That returned stream object is then taken as right operand for the following output stream operation. */ std::cout.write(str, sizeof(str)-1) << "Bye!" << std::endl; /* "Hello!\n" "Bye!\n" is written into the console. */ return 0; }

Method put

The method std::ostream& std::ostream::put(char c) outputs a byte to the stream. The argument is the value of the byte to output. It returns a reference to the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream> int main() { // Outputs a byte with the ASCII value of the character 'Z'. std::cout.put('Z'); // Outputs a byte with the ASCII value of the newline character. std::cout.put('\n'); /* We can do the following, because the method 'put' returns a reference to the object it is called from, which in this case is std::cout. */ std::cout.put('W') << std::endl; return 0; }

Method read

The method std::istream& std::istream::read(char* data, streamsize size) is used to read a fixed amount of bytes from a stream. The first argument is a pointer to the array where to write the bytes read. The second argument is the number of bytes to read. It returns a reference to the stream object is it called from. Note that with files, the method stops when either the number of bytes specified is read or the end of the file is reached. When the stream is linked to the console, it waits for the number of bytes specified to be entered. If the number of characters entered inside the console exceeds the number of bytes to read, the bytes in surplus stay in the buffer of std::cin (Buffered stream).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> int main() { char buffer[10]; // Reads 10 bytes from the console. std::cin.read(buffer, 10); // Prints a newline character. std::cout.put('\n'); // Writes the 10 bytes back to the console. std::cout.write(buffer, 10); return 0; }

As you can see, the newline character, created when the enter key is pressed, is considered to be a byte.

Methods unget and putback

Both methods std::istream& std::istream::putback(char c) and std::istream& std::istream::unget() decrease the stream cursor position (If the stream position is not 0 (At the beginning)). The difference is that the method std::istream::unget makes the next input operation on the stream input the last character read again, while std::istream::putback(char c) makes the next input operation read the character given as argument.

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
36
#include <iostream> int main() { char c; // Reads a characters from the console. std::cin >> c; // Writes the character back to the console. std::cout.put(c); // Decreases the cursor position of the stream. std::cin.unget(); // Reads the same character again std::cin >> c; std::cout.put('\n'); // Writes the character to the console. std::cout.put(c); // Makes the next input operation on std::cout read the character 'L'. std::cin.putback('L'); // Reads 'L' from the stream. std::cin >> c; std::cout.put('\n'); // Writes 'L' to the console. std::cout.put(c); return 0; }

Method get

The method std::istream::get has many overloads. The first two are: int std::istream::get(), which reads and returns a byte from the stream, and std::istream& std::istream::get(char& c), which reads a byte from the stream and stores it inside the reference received as argument, and returns a reference to the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> int main() { char c; // Reads 1 byte from the console. c = std::cin.get(); // Prints 1 byte to the console. std::cout.put(c); // Reads 1 byte from the console. std::cin.get(c); // Prints 1 byte to the console. std::cout.put(c); return 0; }

Note that the enter character '\n' is part of the characters read from the console. So, in the example above, if we write the letter 'z' and then we press the enter key, the first input instruction (c = std::cin.get();) will retrieve the character 'z' and the second one (std::cin.get(c);) will retrieve the enter character. However, if we write the letters 'A' and 'B' and then we press the enter key, the first input instruction will retrieve the character 'A' and the second one 'B'.

An other overload

The method std::istream::get also have overloads that allow to read bytes from the console and make them a null-terminated string by adding a zero a the end of the bytes read: std::istream& std::istream::get(char* str, streamsize nb) and std::istream& std::istream::get(char* str, streamsize size, char delim). The first overload reads a string (bytes) until either the newline character is reached, the number of characters specified by the second argument, minus one, is read, or the end of the file is reached (With files only). The second overload does the same as the first, except that it stops at the character specified as last argument instead of the newline character. Note that newline character (Or the character specified as last argument) is not read and stays in the stream buffer (The next input operation will read it). The first argument is a pointer to the array of bytes that will receive the characters read, as a null-terminated string.

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
#include <iostream> int main() { char str[40]; char str2[40]; /* Reads bytes into 'str' until either the newline character is reached or 39 characters has been read. A maximum of 39 characters are read, because a null character is added at the end of the array. If the newline character is reached, it is not read and it stays in the stream for the next input operation to read. */ std::cin.get(str, 40); // Prints, to the console, the string read into 'str'. std::cout << '\n' << str << "\n\n"; /* If the next character in the stream is not a newline character, we send the character back to the stream. Otherwise, we take it off so the next input operation does not read it. */ if(std::cin.get() != '\n') std::cin.unget(); /* Reads characters into 'str2' until either the character '.' is reached or 39 characters has been read. If the character '.' is reached, it is not read and it stays in the stream for the next input operation to read. */ std::cin.get(str2, 40, '.'); // Prints, to the console, the string read into 'str2'. std::cout << '\n' << str2 << std::endl; return 0; }

Method getline

The method std::istream::getline, which two overloads are std::istream& getline(char* str, streamsize nb) and std::istream& getline(char* str, streamsize nb, char delim), does the same as std::istream::get (When used to read a string), except that it takes off the stream the newline character (Or the delimiter character specified as third argument, if the second overload is used) when it reaches it. Both overloads take, as first argument, a pointer to the array of bytes to write the string read to and the size of the array as second argument. The maximum amount of characters read is the size of the array minus one, because a null-character is automatically added to the end of the string read (As long as the size of the array is at least one and even if no character is read).

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
#include <iostream> int main() { char str[30]; char str2[30]; /* Reads characters into 'str' until either the newline character is reached or 29 characters has been read. A maximum of 29 characters are read, because a null character is added at the end of the array. If the newline character '\n' is reached, it is taken off the stream and discarded. */ std::cin.getline(str, 30); // Prints, to the console, the string read into 'str'. std::cout << '\n' << str << "\n\n"; /* Reads characters into 'str2' until either the character '.' is reached or 29 characters has been read. If the character '.' is reached, it is taken off the stream and discarded. */ std::cin.getline(str2, 30, '.'); // Prints, to the console, the string read into 'str2'. std::cout << '\n' << str2 << std::endl; return 0; }

Method peek

The method std::istream& std::istream::peek() is used to retrieve the value of the next byte in the stream, without taking it off of it (Without moving the cursor of the stream). It returns a reference to the stream object. If there is no byte left to read (The end of the stream is reached) and the stream is linked to a file, the value of the macro EOF is returned. If it is linked to the console, it waits for the user to enter a character.

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
#include <iostream> int main() { char buffer[30]; // Reads characters until either 'a' is reached or 29 characters are read. std::cin.get(buffer, 30, 'a'); /* Retrieves the value of the next character (byte) in the stream. However, it does not read it (Does not extract it from the buffer of the stream). */ char c = std::cin.peek(); if(c == EOF) std::cout << "No character left." << std::endl; else { /* The two following output operations should display the same character. */ std::cout << c << std::endl; /* Reads the character from the stream and prints it (The method 'get' returns the ASCII value as an 'int'. We convert it to 'char' so the character associated with it is displayed). */ std::cout << (char) std::cin.get() << std::endl; } return 0; }

Method ignore

The method std::istream& ignore(streamsize n=1, int delim= EOF) is used to input bytes from the stream and throw them away. The first argument is the maximum amount of bytes to discard, which is one by default. If the character specified as second argument is reached, the method stops, and that character is extracted from the stream and thrown away to. By default, the second argument has the value of the macro EOF (End Of File), so the method stops only when n characters has been read or when the end of the stream is reached. Note that even if the value of the second argument is not EOF, the method still stop if the end of the stream is reached. If it is used on a stream linked to the console and the second argument is EOF, the method will stop only when the number of bytes, specified as first argument, is read. The reason is that a stream linked to the console never reaches the end as it waits for the user to input something when the buffer is empty.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream> int main() { /* The next 5 characters entered in the console will be thrown away. */ std::cin.ignore(5); /* All characters until the character '.' is reached will be discarded (Maximum of 5 characters). */ std::cin.ignore(5, '.'); std::string str; // Input a string (word), from the console, inside 'str'. std::cin >> str; // Display, to the console, the string read inside 'str'. std::cout << str << std::endl; return 0; }

Method gcount

The method streamsize std::istream::gcount() const returns the number of bytes (Or characters) read by the last input operation on the stream object it is called from (Does not work with the >> operator).

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
36
37
#include <iostream> int main() { float n; // Reads a floating point number from the console. std::cin >> n; /* Tries to retrieve the number of bytes read, which does not work, because the method gcount does not work with the operator >>. */ std::cout << std::cin.gcount() << std::endl; // The number 0 is printed into the console. // Takes off the newline character from the stream, if there is one, so the following input operation does not read it. if(std::cin.peek() == '\n') std::cin.ignore(); // Takes off one character. char str[40]; // Reads a line of characters from the console. std::cin.getline(str, 40); /* Prints the number of characters read by the last input operation on the stream object std::cin (std::cin.getline(str, 40);). */ std::cout << std::cin.gcount() << std::endl; /* Note that the newline character read, but discarded, is also counted in the number of characters read. */ return 0; }