C++ Programming/Code/IO
Contents |
[edit] I/O
Also commonly referenced as the C++ I/O of the C++ Standard Library, since the library also includes the C Standard library and its I/O implementation, as seen before in the Standard C I/O Section.
Input and output are essential for any computer software, as these are the only means by which the program can communicate with the user. The simplest form of input/output is pure textual, i.e. the application displays in console form, using simple ASCII characters to prompt the user for inputs, which are supplied using the keyboard.
There are many ways for a program to gain input and output, including
- File i/o, that is, reading and writing to files
- Console i/o, reading and writing to a console window, such as a terminal in UNIX-based operating systems or a DOS prompt in Windows.
- Network i/o, reading and writing from a network device
- String i/o, reading and writing treating a string as if it were the input or output device
While these may seem unrelated, they work very similarly. In fact, operating systems that follow the POSIX specification deal with files, devices, network sockets, consoles, and many other things all with one type of handle, a file descriptor. However, low-level interfaces provided by the operating system tend to be difficult to use, so C++, like other languages, provide an abstraction to make programming easier. This abstraction is the stream.
[edit] Character encoding
[edit] American Standard Code for Information Interchange (ASCII) 95 chart
ASCII is a character-encoding scheme based on the ordering of the English alphabet. The 95 ASCII graphic characters numbered from 0x20 to 0x7E (32 to 126 decimal), also known as the printable characters, represent letters, digits, punctuation marks, and a few miscellaneous symbols. The first 32 ASCII characters, from 0x00 to 0x20, are known as control characters. The space character, that denotes the space between words, as produced by the space-bar of a keyboard, represented by code 0x20 (hexadecimal), is considered a non-printing graphic (or an invisible graphic) rather than a control character.
| Binary | Oct | Dec | Hex | Glyph |
|---|---|---|---|---|
| 010 0000 | 040 | 32 | 20 | space |
| 010 0001 | 041 | 33 | 21 | ! |
| 010 0010 | 042 | 34 | 22 | " |
| 010 0011 | 043 | 35 | 23 | # |
| 010 0100 | 044 | 36 | 24 | $ |
| 010 0101 | 045 | 37 | 25 | % |
| 010 0110 | 046 | 38 | 26 | & |
| 010 0111 | 047 | 39 | 27 | ' |
| 010 1000 | 050 | 40 | 28 | ( |
| 010 1001 | 051 | 41 | 29 | ) |
| 010 1010 | 052 | 42 | 2A | * |
| 010 1011 | 053 | 43 | 2B | + |
| 010 1100 | 054 | 44 | 2C | , |
| 010 1101 | 055 | 45 | 2D | - |
| 010 1110 | 056 | 46 | 2E | . |
| 010 1111 | 057 | 47 | 2F | / |
| 011 0000 | 060 | 48 | 30 | 0 |
| 011 0001 | 061 | 49 | 31 | 1 |
| 011 0010 | 062 | 50 | 32 | 2 |
| 011 0011 | 063 | 51 | 33 | 3 |
| 011 0100 | 064 | 52 | 34 | 4 |
| 011 0101 | 065 | 53 | 35 | 5 |
| 011 0110 | 066 | 54 | 36 | 6 |
| 011 0111 | 067 | 55 | 37 | 7 |
| 011 1000 | 070 | 56 | 38 | 8 |
| 011 1001 | 071 | 57 | 39 | 9 |
| 011 1010 | 072 | 58 | 3A | : |
| 011 1011 | 073 | 59 | 3B | ; |
| 011 1100 | 074 | 60 | 3C | < |
| 011 1101 | 075 | 61 | 3D | = |
| 011 1110 | 076 | 62 | 3E | > |
| 011 1111 | 077 | 63 | 3F | ? |
| Binary | Oct | Dec | Hex | Glyph |
|---|---|---|---|---|
| 100 0000 | 100 | 64 | 40 | @ |
| 100 0001 | 101 | 65 | 41 | A |
| 100 0010 | 102 | 66 | 42 | B |
| 100 0011 | 103 | 67 | 43 | C |
| 100 0100 | 104 | 68 | 44 | D |
| 100 0101 | 105 | 69 | 45 | E |
| 100 0110 | 106 | 70 | 46 | F |
| 100 0111 | 107 | 71 | 47 | G |
| 100 1000 | 110 | 72 | 48 | H |
| 100 1001 | 111 | 73 | 49 | I |
| 100 1010 | 112 | 74 | 4A | J |
| 100 1011 | 113 | 75 | 4B | K |
| 100 1100 | 114 | 76 | 4C | L |
| 100 1101 | 115 | 77 | 4D | M |
| 100 1110 | 116 | 78 | 4E | N |
| 100 1111 | 117 | 79 | 4F | O |
| 101 0000 | 120 | 80 | 50 | P |
| 101 0001 | 121 | 81 | 51 | Q |
| 101 0010 | 122 | 82 | 52 | R |
| 101 0011 | 123 | 83 | 53 | S |
| 101 0100 | 124 | 84 | 54 | T |
| 101 0101 | 125 | 85 | 55 | U |
| 101 0110 | 126 | 86 | 56 | V |
| 101 0111 | 127 | 87 | 57 | W |
| 101 1000 | 130 | 88 | 58 | X |
| 101 1001 | 131 | 89 | 59 | Y |
| 101 1010 | 132 | 90 | 5A | Z |
| 101 1011 | 133 | 91 | 5B | [ |
| 101 1100 | 134 | 92 | 5C | \ |
| 101 1101 | 135 | 93 | 5D | ] |
| 101 1110 | 136 | 94 | 5E | ^ |
| 101 1111 | 137 | 95 | 5F | _ |
| Binary | Oct | Dec | Hex | Glyph |
|---|---|---|---|---|
| 110 0000 | 140 | 96 | 60 | ` |
| 110 0001 | 141 | 97 | 61 | a |
| 110 0010 | 142 | 98 | 62 | b |
| 110 0011 | 143 | 99 | 63 | c |
| 110 0100 | 144 | 100 | 64 | d |
| 110 0101 | 145 | 101 | 65 | e |
| 110 0110 | 146 | 102 | 66 | f |
| 110 0111 | 147 | 103 | 67 | g |
| 110 1000 | 150 | 104 | 68 | h |
| 110 1001 | 151 | 105 | 69 | i |
| 110 1010 | 152 | 106 | 6A | j |
| 110 1011 | 153 | 107 | 6B | k |
| 110 1100 | 154 | 108 | 6C | l |
| 110 1101 | 155 | 109 | 6D | m |
| 110 1110 | 156 | 110 | 6E | n |
| 110 1111 | 157 | 111 | 6F | o |
| 111 0000 | 160 | 112 | 70 | p |
| 111 0001 | 161 | 113 | 71 | q |
| 111 0010 | 162 | 114 | 72 | r |
| 111 0011 | 163 | 115 | 73 | s |
| 111 0100 | 164 | 116 | 74 | t |
| 111 0101 | 165 | 117 | 75 | u |
| 111 0110 | 166 | 118 | 76 | v |
| 111 0111 | 167 | 119 | 77 | w |
| 111 1000 | 170 | 120 | 78 | x |
| 111 1001 | 171 | 121 | 79 | y |
| 111 1010 | 172 | 122 | 7A | z |
| 111 1011 | 173 | 123 | 7B | { |
| 111 1100 | 174 | 124 | 7C | | |
| 111 1101 | 175 | 125 | 7D | } |
| 111 1110 | 176 | 126 | 7E | ~ |
[edit] Streams
A stream is a type of object from which we can take values, or to which we can pass values. This is done transparently in terms of the underlying code that demonstrates the use of the std::cout stream, known as the standard output stream.
// 'Hello World!' program #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return 0; }
Almost all input and output one ever does can be modeled very effectively as a stream. Having one common model means that one only has to learn it once. If you understand streams, you know the basics of how to output to files, the screen, sockets, pipes, and anything else that may come up.
A stream is an object that allows one to push data in or out of a medium, in order. Usually a stream can only output or can only input. It is possible to have a stream that does both, but this is rare. One can think of a stream as a car driving along a one-way street of information. An output stream can insert data and move on. It (usually) cannot go back and adjust something it has already written. Similarly, an input stream can read the next bit of data and then wait for the one that comes after it. It does not skip data or rewind and see what it had read 5 minutes ago.
The semantics of what a stream's read and write operations do depend on the type of stream. In the case of a file, an input file stream reads the file's contents in order without rewinding, and an output file stream writes to the file in order. For a console stream, output means displaying text, and input means getting input from the user via the console. If the user has not inputted anything, then the program blocks, or waits, for the user to enter in something.
[edit] iostream
iostream is a header file used for input/output. Part of the C++ standard library. The name stands for Input/Output Stream. In C++ there is no special syntax for streaming data input or output. Instead, these are combined as a library of functions. Like we have seen with the C Standard Library use of <cstdio> header, iostream provides basic OOP services for I/O.
The <iostream> automatically defines and uses a few standard objects:
cin, an object of the istream class that reads data from the standard input device.cout, an object of the ostream class, which displays data to the standard output device.cerr, another object of the ostream class that writes unbuffered output to the standard error device.clog, like cerr, but uses buffered output.
for sending data to and from the standard streams input, output, error (unbuffered), and error (buffered) respectively. As part of the C++ standard library, these objects are a part of the std namespace.
- Standard input, output, and error
The most common streams one uses are cout, cin, and cerr (pronounced "c out", "c in", and "c err(or)", respectively). They are defined in the header <iostream>. Usually, these streams read and write from a console or terminal. In UNIX-based operating systems, such as Linux and Mac OS X, the user can redirect them to other files, or even other programs, for logging or other purposes. They are analogous to stdout, stdin, and stderr found in C. cout is used for generic output, cin is used for input, and cerr is used for printing errors. (cerr typically goes to the same place as cout, unless one or both is redirected, but it is not buffered and allows the user to fine-tune which parts of the program's output is redirected where.)
[edit] Output
The standard syntax for outputting to a stream, in this case, cout, is
cout << some_data << some_more_data;
Example
#include <iostream> using namespace std; int main() { int a = 1; cout << "Hello world! " << a << '\n'; return 0; }
Result of Execution
Hello world! 1
To add a line break, send a newline character, \n or use std::endl, which writes a newline and flushes the stream's buffer.
Example
#include <iostream> #include <ostream> using namespace std; int main() { int a = 1; char x = 13; cout << "Hello world!" << "\n" << a << endl << x << endl; return 0; }
Execution
Hello world! 1
It is always a good idea to end your output with a blank line, so as to not mess up with user's terminals.
As seen in the "Hello World!" program, we direct the output to std::cout. This means that it is a member of the standard library. For now, don't worry about what this means; we will cover the library and namespaces in later chapters.
What you do need to remember is that, in order to use the output stream, you must include a reference to the standard IO library, as shown here:
#include <iostream>
This opens up a number of streams, functions and other programming devices which we can now use. For this section, we are interested in two of these; std::cout and std::endl.
Once we have referenced the standard IO library, we can use the output stream very simply. To use a stream, give its name, then pipe something in or out of it, as shown:
std::cout << "Hello, world!";
The << operator feeds everything to the right of it into the stream. We have essentially fed a text object into the stream. That's as far as our work goes; the stream now decides what to do with that object. In the case of the output stream, it's printed on-screen.
We're not limited to only sending a single object type to the stream, nor indeed are we limited to one object a time. Consider the examples below:
std::cout << "Hello, " << "Joe"<< std::endl; std::cout << "The answer to life, the universe and everything is " << 42 << std::endl;
As can be seen, we feed in various values, separated by a pipe character. The result comes out something like:
Hello, Joe The answer to life, the universe and everything is 42
You will have noticed the use of std::endl throughout some of the examples so far. This is the newline constant. It is a member of the standard IO library, and comes "free" when we instantiate that in order to use the output stream. When the output stream receives this constant, it starts a new line in the console.
And of course, we're not limited to sending only ONE newline, either:
std::cout << "Hello, " << "Joe" << std::endl << std::endl; std::cout << "How old are you?";
Which produces something like:
Hello, Joe How old are you?
[edit] Input
What would be the use of an application that only ever outputted information, but didn't care about what its users wanted? Minimal to none. Fortunately, inputting is as easy as outputting when you're using the stream.
The standard input stream is called std::cin and is used very similarly to the output stream. Once again, we instantiate the standard IO library:
#include <iostream>
This gives us access to std::cin (and the rest of that class). Now, we give the name of the stream as usual, and pipe output from it into a variable. A number of things have to happen here, demonstrated in the example below:
#include <iostream> int main(int argc, char argv[]) { int a; std::cout << "Hello! How old are you? "; std::cin >> a; std::cout << "You're really " << a << " years old?" << std::endl; return 0; }
We instantiate the standard IO library as usual, and call our main function in the normal way. Now we need to consider where the user's input goes. This calls for a variable (discussed in a later chapter) which we declare as being called a.
Next, we send some output, asking the user for their age. The real input happens now; everything the user types until they hit Enter is going to be stored in the input stream. We pull this out of the input stream and save it in our variable.
Finally, we output the user's age, piping the contents of our variable into the output stream.
Note: You will notice that if anything other than a whole number is entered, the program will crash. This is due to the way in which we set up our variable. Don't worry about this for now; we will cover variables later on.
[edit] A Program Using User Input
The following program inputs two numbers from the user and prints their sum:
#include <iostream> int main() { int num1, num2; std::cout << "Enter number 1: "; std::cin >> num1; std::cout << "Enter number 2: "; std::cin >> num2; std::cout << "The sum of " << num1 << " and " << num2 << " is " << num1 + num2 << ".\n"; return 0; }
Just like std::cout which represents the standard output stream, the C++ library provides (and the iostream header declares) the object std::cin representing standard input, which usually gets input from the keyboard. The statement:
std::cin >> num1;
uses the extraction operator (>>) to get an integer input from the user. When used to input integers, any leading whitespace is skipped, a sequence of valid digits optionally preceded by a + or - sign is read and the value stored in the variable. Any remaining characters in the user input are not consumed. These would be considered next time some input operation is performed.
If you want the program to use a function from a specific namespace, normally you must specify which namespace the function is in. The above example calls to cout, which is a member of the std namespace (hence std::cout). If you want a program to specifically use the std namespace for an identifier, which essentially removes the need for all future scope resolution (e.g. std::), you could write the above program like this:
#include <iostream> using namespace std; int main() { int num1, num2; cout << "Enter number 1: "; cin >> num1; cout << "Enter number 2: "; cin >> num2; cout << "The sum of " << num1 << " and " << num2 << " is " << num1 + num2 << ".\n"; return 0; }
Please note that 'std' namespace is the namespace defined by standard C++ library.
[edit] Manipulators
A manipulator is a function that can be passed as an argument to a stream in different circumstances. For example, the manipulator 'hex' will cause the stream object to format subsequent integer input to the stream in hexadecimal instead of decimal. Likewise, 'oct' results in integers displaying in octal, and 'dec' reverts back to decimal.
Example
#include <iostream> using namespace std; int main() { cout << dec << 16 << ' ' << 10 << endl; cout << oct << 16 << ' ' << 10 << endl; cout << hex << 16 << ' ' << 10 << endl; return 0; }
Execution
16 10 20 12 10 a
There are many manipulators which can be used in conjunction with streams to simplify the formatting of input. For example, 'setw()' sets the field width of the data item next displayed. Used in conjunction with 'left' and 'right'(which set the justification of the data), 'setw' can easily be used to create columns of data.
Example
#include <iostream> #include <iomanip> using namespace std; int main() { cout << setw(10) << right << 90 << setw(8) << "Help!" << endl; cout << setw(10) << left << 45 << setw(8) << "Hi!" << endl; return 0; }
Execution
90 Help!
45 Hi!
The data in the top row display at the right of the columns created by 'setw', while in the next row, the data is left justified in the column. Please note the inclusion of a new library 'iomanip'. Most formatting manipulators require this library.
Here are some other manipulators and their uses:
| Manipulator | Function |
|---|---|
| boolalpha | displays boolean values as 'true' and 'false' instead of as integers. |
| noboolalpha | forces bools to display as integer values |
| showuppercase | converts strings to uppercase before displaying them |
| noshowuppercase | displays strings as they are received, instead of in uppercase |
| fixed | forces floating point numbers to display with a fixed number of decimal places |
| scientific | displays floating point numbers in scientific notation |
[edit] Buffers
Most stream objects, including 'cout' and 'cin', have an area in memory where the information they are transferring sits until it is asked for. This is called a 'buffer'. Understanding the function of buffers is essential to mastering streams and their use.
Example
#include <iostream> using namespace std; int main() { int num1, num2; cin >> num1; cin >> num2; cout << "Number1: " << num1 << endl << "Number2: " << num2 << endl; return 0; }
Execution 1
>74 >27 Number1: 74 Number2: 27
The inputs are given separately, with a hard return between them. '>' denotes user input.
Execution 2
>74 27 Number1: 74 Number2: 27
The inputs are entered on the same line. They both go into the 'cin' stream buffer, where they are stored until needed. As 'cin' statements are executed, the contents of the buffer are read into the appropriate variables.
Execution 3
>74 27 56 Number1: 74 Number2: 27
In this example, 'cin' received more input than it asked for. The third number it read in, 56, was never inserted into a variable. It would have stayed in the buffer until 'cin' was called again. The use of buffers can explain many strange behaviors that streams can exhibit.
Example
#include <iostream> using namespace std; int main() { int num1, num2, num3; cin >> num1 >> num2; cout << "Number1: " << num1 << endl << "Number2: " << num2 << endl; cin >> num3; cout << "Number3: " << num3 << endl; return 0; }
Execution
>45 89 37 Number1: 45 Number2: 89 Number3: 37
Notice how all three numbers were entered at the same time in one line, but the stream only pulled them out of the buffer when they were asked for. This can cause unexpected output, since the user might accidentally put an extra space into his input. A well written program will test for this type of unexpected input and handle it gracefully.
[edit] ios
ios is a header file in the C++ standard library which defines several types and functions basic to the operation of iostreams. This header is typically included automatically by other iostream headers. Programmers rarely include it directly.
[edit] Typedefs
| Name | description |
|---|---|
ios |
Supports the ios class from the old iostream library. |
streamoff |
Supports internal operations. |
streampos |
Holds the current position of the buffer pointer or file pointer. |
streamsize |
Specifies the size of the stream. |
wios |
Supports the wios class from the old iostream library. |
wstreampos |
Holds the current position of the buffer pointer or file pointer. |
[edit] Manipulators
| Name | description |
|---|---|
boolalpha |
Specifies that variables of type bool appear as true or false in the stream. |
dec |
Specifies that integer variables appear in base 10 notation. |
fixed |
Specifies that a floating-point number is displayed in fixed-decimal notation. |
hex |
Specifies that integer variables appear in base 16 notation. |
internal |
Causes a number's sign to be left justified and the number to be right justified. |
left |
Causes text that is not as wide as the output width to appear in the stream flush with the left margin. |
noboolalpha |
Specifies that variables of type bool appear as 1 or 0 in the stream. |
noshowbase |
Turns off indicating the notational base in which a number is displayed. |
noshowpoint |
Displays only the whole-number part of floating-point numbers whose fractional part is zero. |
noshowpos |
Causes positive numbers to not be explicitly signed. |
noskipws |
Cause spaces to be read by the input stream. |
nounitbuf |
Causes output to be buffered and processed when the buffer is full. |
nouppercase |
Specifies that hexadecimal digits and the exponent in scientific notation appear in lowercase. |
oct |
Specifies that integer variables appear in base 8 notation. |
right |
Causes text that is not as wide as the output width to appear in the stream flush with the right margin. |
scientific |
Causes floating point numbers to be displayed using scientific notation. |
showbase |
Indicates the notational base in which a number is displayed. |
showpoint |
Displays the whole-number part of a floating-point number and digits to the right of the decimal point even when the fractional part is zero. |
showpos |
Causes positive numbers to be explicitly signed. |
skipws |
Cause spaces to not be read by the input stream. |
unitbuf |
Causes output to be processed when the buffer is not empty. |
uppercase |
Specifies that hexadecimal digits and the exponent in scientific notation appear in uppercase. |
[edit] Classes
| Name | description |
|---|---|
basic_ios |
The template class describes the storage and member functions common to both input streams (of template class basic_istream) and output streams (of template class basic_ostream) that depend on the template parameters. |
fpos |
The template class describes an object that can store all the information needed to restore an arbitrary file-position indicator within any stream. |
ios_base |
The class describes the storage and member functions common to both input and output streams that do not depend on the template parameters. |
[edit] fstream
With cout and cin, we can do basic communication with the user. For more complex io, we would like to read from and write to files. This is done with file stream classes, defined in the header <fstream>. ofstream is an output file stream, and ifstream is an input file stream.
- Files
To open a file, one can either call open on the file stream or, more commonly, use the constructor. One can also supply an open mode to further control the file stream. Open modes include
- ios::app Leaves the file's original contents and appends new data to the end.
- ios::out Outputs new data in the file, removing the old contents. (default for ofstream)
- ios::in Reads data from the file. (default for ifstream)
Example
// open a file called Test.txt and write "HELLO, HOW ARE YOU?" to it #include <fstream> using namespace std; int main() { ofstream file1; file1.open("file1.txt", ios::app); file1 << "This data will be appended to the file file1.txt\n"; file1.close(); ofstream file2("file2.txt"); file2 << "This data will replace the contents of file2.txt\n"; return 0; }
The call to close() can be omitted if you do not care about the return value (whether it succeeded); the destructors will call close when the object goes out of scope.
If an operation (e.g. opening a file) was unsuccessful, a flag is set in the stream object. You can check the flags' status using the bad() or fail() member functions, which return a boolean value. The stream object doesn't throw any exceptions in such a situation; hence manual status check is required. See reference for details on bad() and fail().
[edit] Text input until EOF/error/invalid input
Input from the stream infile to a variable data until one of the following:
- EOF reached on infile.
- An error occurs while reading from infile (e.g., connection closed while reading from a remote file).
- The input item is invalid, e.g. non-numeric characters, when data is of type int.
#include <iostream> // ... while (infile >> data) { // manipulate data here }
Note that the following is not correct:
#include <iostream> // ... while (!infile.eof()) { infile >> data; // wrong! // manipulate data here }
This will cause the last item in the input file to be processed twice, because eof() does not return true until input fails due to EOF.
[edit] ostream
- Classes and output streams
It is often useful to have your own classes' instances compatible with the stream framework. For instance, if you defined the class Foo like this:
class Foo { public: Foo() : x(1), y(2) { } int x, y; };
You will not be able to pass its instance to cout directly using the '<<' operator, because it is not defined for these two objects (Foo and ostream). What needs to be done is to define this operator and thus bind the user-defined class with the stream class.
ostream& operator<<(ostream& output, Foo& arg) { output << arg.x << "," << arg.y; return output; }
Now this is possible:
Foo my_object; cout << "my_object's values are: " << my_object << endl;
The operator function needs to have 'ostream&' as its return type, so chaining output works as usual between the stream and objects of type Foo:
Foo my1, my2, my3; cout << my1 << my2 << my3;
This is because (cout << my1) is of type ostream&, so the next argument (my2) can be appended to it in the same expression, which again gives an ostream& so my3 can be appended and so on.
If you decided to restrict access to the member variables x and y (which is probably a good idea) within the class Foo, i.e.:
class Foo { public: Foo() : x(1), y(2) { } private: int x, y; };
you will have trouble, because the global operator<< function doesn't have access to the private variables of its second argument. There are two possible solutions to this problem:
1. Within the class Foo, declare the operator<< function as the classes' friend which grants it access to private members, i.e. add the following line to the class declaration:
friend ostream& operator<<(ostream& output, Foo& arg);
Then define the operator<< function as you normally would (note that the declared function is not a member of Foo, just its friend, so don't try defining it as Foo::operator<<).
2. Add public-available functions for accessing the member variables and make the operator<< function use these instead:
class Foo { public: Foo() : x(1), y(2) { } int get_x() { return x; } int get_y() { return y; } private: int x, y; }; ostream& operator<<(ostream& output, Foo& arg) { output << arg.get_x() << "," << arg.get_y(); return output; }