Total Pageviews

Sunday, November 14, 2010

Lesson 61 -C++-Formatting Cout Output in C++ using iomanip

Creating cleanly formatted output is a common programming requirement--it improves your user interface and makes it easier to read any debugging messages that you might print to the screen. In C, formatted output works via the printf statement, but in C++, you can create nicely formatted output to streams such as cout. This tutorial covers a set of basic I/O manipulations possible in C++ from the iomanip header file. Note that all of the functions in the iomanip header are inside the std namespace, so you will need to either prefix your calls with "std::" or put "using namespace std;" before using the functions.

Dealing with Spacing Issues using iomanip

A principle aspect of nicely formatted output is that the spacing looks right. There aren't columns of text that are too long or too short, and everything is appropriately aligned. This section deals with ways of spacing output correctly.
Setting the field width with setw

The std::setw function allows you to set the minimum width of the next output via the insertion operator. setw takes, one argument, the width of the next output (insertion), an integer. if the next output is too short, then spaces will be used for padding. There is no effect if the output is longer than the width--note that the output won't be truncated. The only strange thing about setw is that its return value must be inserted into the stream. The setw function has no effect if it is called without reference to a stream. A simple example is
using namespace std;
cout< people;
// fill the vector somehow

int field_one_width = 0, field_two_width = 0;

// get the max widths

for ( vector::iterator iter = people.begin();
iter != people.end();
++iter )
{
if ( iter->firstname.length() > field_one_width )
{
field_one_width = iter->firstname.length();
}
if ( iter->lastname.length() > field_two_width )
{
field_two_width = iter->lastname.length();
}
}

// print the elements of the vector
for ( vector::iterator iter = people.begin();
iter != people.end();
++iter )
{
cout<firstname;
cout<<" "; cout<lastname;
}
Note that the space output between the two fields wasn't strictly necessary because we could have added it by changing the first call to setw to set the width to one more than the longest first name (since it would use a space as the padding for the extra character).
Printing Numbers

Another challenge in creating nice output is correctly formatting numbers; for instance, when printing out a hexadecimal value, it would be nice if it were preceded by the "0x" prefix. More generally, it's nice to correctly set the number of trailing zeros after a decimal place.
Setting the precision of numerical output with setprecision

The setprecision function can be used to set the maximum number of digits that are displayed for a number. Like setw, it should be inserted into the stream. In fact, its usage is very similar to setw in all respects. For instance, to print the number 2.71828 to 3 decimal places:
std::cout << setprecision(3) << 2.71828;
Note that setprecision will change the precision until the next time it is passed into a given stream. So changing the above example to also print out 1.412 would result in the output of
2.71 1.41
Output in different bases

In computer science, frequently numbers need to be printed in octal or hexadecimal. The setbase function returns a value that can be passed into a stream to set the base of numbers to either base 8, 10, or 16. The input number is still read as a number in base ten, but it is printed in the given base. For instance,
std::cout << setbase(16) << 32;
will print out "20", which is 32 written in base 16. Note that you can use dec, oct, and hex as shorthand for setbase(10), setbase(8), and setbase(16) respectively when inserting into a stream. If you wish to include an indication of the base along with the printed number, you can use the setiosflags function, again passed into a stream, with an input of ios_base::showbase. Using the ios_base::showbase flag will append a "0x" in front of hexadecimal numbers and a 0 in front of octal numbers. Decimal numbers will be printed as normal.
std::cout <<
std::cout<< setbase(16) << 32;
This should get you started with the ability to create nicely formatted output in C++ without having to resort to returning to printf!

No comments:

Post a Comment