Learn About Input and Output in C++

01
of 08

A New Way to Output

Program code
traffic_analyzer/Getty Images

C++ retains very high backwards compatibility with C, so <stdio.h> can be included to give you access to the printf() function for output. However, the I/O provided by C++ is significantly more powerful and more importantly type safe. You can still also use scanf() for input but the type safety features that C++ provides means that your applications will be more robust if you use C++.

In the previous lesson, this was touched on with an example that used cout. Here we'll go into a bit more depth starting with output first as it tends to be more used than input.

The iostream class provides access to the objects and methods you need for both output and input. Think of i/o in terms of streams of bytes- either going from your application to a file, the screen or a printer - that's output, or from the keyboard - that's input.

Output with Cout

If you know C, you may know that << is used to shift bits to the left. Eg 3 << 3 is 24. Eg left shift doubles the value so 3 left shifts multiplies it by 8.

In C++, << has been overloaded in the ostream class so that int, float, and strings types (and their variants- eg doubles) are all supported. This is how you do text output, by stringing together multiple items between <<.


cout << "Some Text" << intvalue << floatdouble << endl;

This peculiar syntax is possible because each of the << is actually a function call which returns a reference to an ostream object. So a line like the above is actually like this


cout.<<("some text").cout.<<( intvalue ).cout.<<(floatdouble).cout.<<(endl) ;

The C function printf was able to format output using Format Specifiers such as %d. In C++ cout can also format output but uses a different way of doing it.

02
of 08

Using Cout to Format Output

The object cout is a member of the iostream library. Remember that this has to be included with a


#include <iostream>

This library iostream is derived from ostream (for output) and istream for input.

Formatting of text output is done by inserting manipulators into the output stream.

What Is a Manipulator?

It's a function that can alter the characteristics of the output (and input) stream. On the previous page we saw that << was an overloaded function that returned a reference to the calling object e.g. cout for output or cin for input. All manipulators do this so you can include them in the output << or input >>. We'll look at input and >> later on in this lesson.


count << endl;

endl is a manipulator which ends the line (and starts a new one). It is a function that can also be called in this way.


endl(cout) ;

Though in practice you wouldn't do that. You use it like this.


cout << "Some Text" << endl << endl; // Two blank lines

Files Are Just Streams

Something to bear in mind that with much development these days being done in GUI applications, why would you need text I/O functions? Isn't that just for console applications? Well you will probably do file I/O and you can use them there as well but also what is output to screen usually needs formatting as well. Streams are a very flexible way of handling input and output and can work with

  • Text I/O. As in console applications.
  • Strings. Handy for formatting.
  • File I/O.

Manipulators Again

Although we have been using the ostream class, it is a derived class from the ios class which derives from the ios_base. This ancestor class defines the public functions which are manipulators.

03
of 08

List of Cout Manipulators

Manipulators can be defined in input or output streams. These are objects that return a reference to the object and are placed between pairs of <<. Most of the manipulators are declared in <ios>, but endl, ends and flush come from <ostream>. Several manipulators take one parameter and these come from <iomanip>.

Here's a more detailed list.

From <ostream>

  • endl - Ends the line and calls flush.
  • ends - Inserts '\0' ( NULL) into the stream.
  • flush - Force the buffer to be output immediately.

From <ios>. Most are declared in <ios_base> the ancestor of <ios>. I've grouped them by function rather than alphabetically.

  • boolalpha - Insert or extract bool objects as "true" or "false".
  • noboolalpha - Insert or extract bool objects as numeric values.

 

  • fixed - Insert floating-point values in fixed format.
  • scientific - Insert floating-point values in scientific format.

 

  • internal - Internal-justify.
  • left - Left-justify.
  • right - Right-justify.

  • dec - Insert or extract integer values in decimal format.
  • hex - Insert or extract integer values in hexadecimal (base 16) format.
  • oct - Insert or extract values in octal (base 8) format.

 

  • noshowbase - Do not prefix value with its base.
  • showbase - Prefix value with its base.
  • noshowpoint - Do not show decimal point if not necessary.
  • showpoint - Always show decimal point when inserting floating-point values.
  • noshowpos - Don't insert plus sign (+) if number >= 0.
  • showpos - Do insert plus sign (+) if number >=0.
  • noskipws - Do not skip initial white space on extracting.
  • skipws - Skip initial white space on extracting.
  • nouppercase - Don't replace lowercase letters by uppercase equivalents.
  • uppercase - Replace lowercase letters by uppercase equivalents.

 

  • unitbuf - Flush buffer after an insert.
  • nounitbuf - Don't flush buffer after each insert.

04
of 08

Examples Using Cout

 // ex2_2cpp 
 
 #include "stdafx.h"
 #include <iostream>
 
 using namespace std;
 
 int main(int argc, char* argv[])
 {
 	cout.width(10) ;
 cout << right << "Test" << endl;
 	cout << left << "Test 2" << endl;
 	cout << internal <<"Test 3" << endl;
 	cout << endl;
 	cout.precision(2) ;
 	cout << 45.678 << endl;
 	cout << uppercase << "David" << endl;
 	cout.precision(8) ;
 cout << scientific << endl;
 	cout << 450678762345.123 << endl;
 cout << fixed << endl;
 	cout << 450678762345.123 << endl;
 	cout << showbase << endl;
 	cout << showpos << endl;
 cout << hex << endl;
 	cout << 1234 << endl;
 cout << oct << endl;
 	cout << 1234 << endl;
 cout << dec << endl;
 	cout << 1234 << endl;
 	cout << noshowbase << endl;
 	cout << noshowpos << endl;
 cout.unsetf(ios::uppercase) ;
 cout << hex << endl;
 	cout << 1234 << endl;
 cout << oct << endl;
 	cout << 1234 << endl;
 cout << dec << endl;
 	cout << 1234 << endl;
 	return 0;
 }
 

The output from this is below, with one or two extra line spaces removed for clarity.

 Test
 Test 2
 Test 3
 46
 David
 
 4.50678762E+011
 
 450678762345.12299000
 
 0X4D2
 02322
 +1234
 
 4d2
 2322
 1234
 

Note: Despite the uppercase, David is printed as David and not DAVID. This is because uppercase only affects generated output- e.g. numbers printed in hexadecimal. So the hex output 4d2 is 4D2 when uppercase is in operation.

Also, most of these manipulators actually set a bit in a flag and it is possible to set this directly with

 cout.setf() 

and clear it with

 cout.unsetf() 

05
of 08

Using Setf and Unsetf to Manipulate I/O Formatting

The function setf has two overloaded versions shown below. While unsetf just clears the specified bits.

 setf( flagvalues) ;
 setf( flagvalues, maskvalues) ;
 unsetf( flagvalues) ;
 

The variable flags is derived by ORing together all the bits you want with |. So if you want scientific, uppercase and boolalpha then use this. Only the bits passed in as the parameter are set. The other bits are left unchanged.

 cout.setf( ios_base::scientific | ios_base::uppercase | ios_base::boolalpha) ;
 cout << hex << endl;
 cout << 1234 << endl;
 cout << dec << endl;
 cout << 123400003744.98765 << endl;
 bool value=true;
 cout << value << endl;
 cout.unsetf( ios_base::boolalpha) ;
 cout << value << endl;
 

Produces

 4D2
 1.234000E+011
 true
 1
 

Masking Bits

The two parameter version of setf uses a mask. If the bit is set in both the first and second parameters then it gets set. If the bit is only in the second parameter then it is cleared. The values adjustfield, basefield and floatfield (listed below) are composite flags, that is several flags Or'd together. For basefield with the values 0x0e00 is the same as dec | oct | hex. So

 setf( ios_base::hex,ios_basefield ) ; 

clears all three flags then sets hex. Similarly adjustfield is left | right | internal and floatfield is scientific | fixed.

List of Bits

This list of enums is taken from Microsoft Visual C++ 6.0. The actual values used are arbitrary- another compiler may use different values.

 skipws = 0x0001
 unitbuf = 0x0002
 uppercase = 0x0004
 showbase = 0x0008
 showpoint = 0x0010
 showpos = 0x0020
 left = 0x0040
 right = 0x0080
 internal = 0x0100
 dec = 0x0200
 oct = 0x0400
 hex = 0x0800
 scientific = 0x1000
 fixed = 0x2000
 boolalpha = 0x4000
 adjustfield = 0x01c0
 basefield = 0x0e00,
 floatfield = 0x3000
 _Fmtmask = 0x7fff,
 _Fmtzero = 0
 
 

06
of 08

About Clog and Cerr

Like cout, clog and cerr are pre-defined objects defined in ostream. The iostream class inherits from both ostream and istream so that's why the cout examples can use iostream.

Buffered and Unbuffered

  • Buffered - All output is temporarily stored in a buffer and then dumped to screen in one go. Both cout and clog are buffered.
  • Unbuffered- All output goes immediately to the output device. An example of an unbuffered object is cerr.

The example below demonstrates that cerr is used in the same way as cout.

 
 #include <iostream>
 
 using namespace std;
 
 int _tmain(int argc, _TCHAR* argv[])
 { cerr.width(15) ;
 	cerr.right;
 	cerr << "Error" << endl;
 	return 0;
 }
 

The main problem with buffering, is if the program crashes then the buffer contents are lost and it's harder to see why it crashed. Unbuffered output is immediate so sprinkling a few lines like this through the code might come in useful.

 cerr << "Entering Dangerous function zappit" << endl; 

The Logging Problem

Building a log of program events can be a useful way to spot difficult bugs- the type that only occur now and then. If that event is a crash though, you have the problem- do you flush the log to disk after every call so you can see events right up to the crash or keep it in a buffer and periodically flush the buffer and hope you don't lose too much when the crash occurs?

07
of 08

Using Cin for Input: Formatted Input

There are two types of input.

  • Formatted. Reading input as numbers or of a certain type.
  • Unformatted. Reading bytes or strings. This gives much greater control over the input stream.

Here is a simple example of formatted input.

 // excin_1.cpp : Defines the entry point for the console application.
 
 #include "stdafx.h" // Microsoft only
 #include <iostream>
 
 using namespace std;
 
 int main(int argc, char* argv[])
 {
 	int a = 0;
 	float b = 0.0;
 	int c = 0;
 	cout << "Please Enter an int, a float and int separated by spaces" <<endl;
 	cin >> a >> b >> c;
 	cout << "You entered " << a << " " << b << " " << c << endl;
 	return 0;
 }
 

This uses cin to read three numbers (int, float,int) separated by spaces. You must press enter after typing the number.

3 7.2 3 will output "You entered 3 7.2 3".

Formatted Input has Limitations!

If you enter 3.76 5 8, you get "You entered 3 0.76 5", all other values on that line are lost. That is behaving correctly, as the . is not part of the int and so marks the start of the float.

Error Trapping

The cin object sets a fail bit if the input was not successfully converted. This bit is part of ios and can be read by use of the fail() function on both cin and cout like this.

 if (cin.fail() ) // do something
 

Not surprisingly, cout.fail() is rarely set, at least on screen output. In a later lesson on file I/O, we'll see how cout.fail() can become true. There is also a good() function for cin, cout etc.

08
of 08

Error Trapping in Formatted Input

Here is an example of input looping until a floating point number has been correctly entered.

 // excin_2.cpp 
 
 #include "stdafx.h" // Microsoft only
 #include <iostream>
 
 using namespace std;
 
 int main(int argc, char* argv[])
 {
 float floatnum;
 cout << "Enter a floating point number:" <<endl;
 while(!(cin >> floatnum))
 { 
 cin.clear() ;
 cin.ignore(256,'\n') ;
 cout << "Bad Input - Try again" << endl;
 }
 cout << "You entered " << floatnum << endl;
 return 0;
 }
 

This example requests a float number and only exits when it has one. If it cannot convert the input, it outputs an error message and calls

clear()

to clear the fail bit. The

ignore

function skips all the rest of the input line. 256 is a sufficiently large number of characters that the \n will be reached before all 256 have been read.

Note: An input such as 654.56Y will read all the way up to the Y, extract 654.56 and exit the loop. It is considered valid input by cin

Unformatted Input

This is a more powerful way of inputting characters or entire lines, rather than keyboard input but that will be left for a later lesson on file

I/O

.

Keyboard Entry

All the input, using

cin

requires the

Enter

or

Return

key to be pressed. Standard C++ does not provide a way to read characters directly from a keyboard. In future lessons we'll see how to do that with third party libraries.

This ends the lesson.