Chapter 4B
NUMERIC DATA TYPES
AND FORMATTING
As discussed in Chapter 1, a variable is a name assigned to a first byte of the necessary memory to store a value. However the compiler needs to know size of the memory to reserve to hold the value beginning with that memory location. This is where the type comes in. In a 16-bit computer for an integer 2 bytes are used, float 4 bytes, double 8 bytes, and character and bool 1 byte each. The size of memory reserved by the compiler you are using can be determined by the operator sizeof.
For example, cout << sizeof(x); if x is an integer, either a 2 or 4 will be displayed.
Some of these types can be signed or unsigned. Unsigned can hold much larger number. For example, in a signed integer variable the range of values are -32,768 to 32,767. In an unsigned integer this range is from 0 to 65,535. Float and double are real numbers, the difference is in their precision. The major differences between integers and real numbers are as follows.
When outputing a real number it is often necessary to indicate the number of decimal digits we want to display. When dealing with dollars there is little reason to go beyond two decimal points. We can use setprecision(n) which is a manipulator available from <iomanip.h>, to indicate the decimal precision we require. For example cout << setprecision(2) << dollars; will display dollars with 2 decimal point precision. The last decimal digit will be rounded of. Consider the following program:
Program 6-1
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << 28 <<" " <<28*1.128 <<endl;
cout << 123 << " " <<123*11.228 <<endl;
return 0;
}
Program Run 6-1:
28 31.584
123 1381.04
Press any key to continue
The columns in the above program do not line up. Now consider the following program and its formatted output.. The integers line up. But even though we used the setprecion(2), the real numbers are displayed differently. Obviously for real numbers the setprecision alone is not enough. In Program 6-3, setw, setiosflags and setprecision are added. This seems to have fixed the problem. Here the ios::fixed causes the real number to be output in fixed point format instead of exponential format.
Program 6-2
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << setw(5)<<28 <<" " <<setprecision(2) << 28*1.128 <<endl;
cout << setw(5) <<123 << " " <<setprecision(2) << 123*11.228 <<endl;
return 0;
}
Program Run 6-2
28 32
123 1.4e+003
Press any key to continue
Program 6-3.
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << setw(5)<<28
<<setw(10)<<setiosflags(ios::fixed) <<setprecision(2) << 28*1.128 <<endl;
cout << setw(5) <<123
<<setw(10)<<setiosflags(ios::fixed) <<setprecision(2) << 123*11.228 <<endl;
return 0;
}
Program Run 6-3.
28 31.58
123 1381.04
Press any key to continue.
At the end of this chapter a more complete discussion is presented on this topic. In chapter 1 you were introduced to the escape character set \n to give a new line. There are other useful escape sequences. Here are some:
\b move back one space
\f move to next page
\t tab over
\\ prints a back slash
\' prints a single quote.
IOMANIP provides several input and output format manipulators. Here is a summary of the most commonly used ones. An explanation of numeric formatting also is given. This section is obtained from the Visual C++ help.
SETIOSFLAGS
ios::skipws Skip white space on input.
ios::left Left-align values; pad on the right with the fill character.
ios::right Right-align values; pad on the left with the fill character (default alignment).
ios::internal Add fill characters after any leading sign or base indication, but before the value.
ios::dec Format numeric values as base 10 (decimal) (default radix).
ios::oct Format numeric values as base 8 (octal).
ios::hex Format numeric values as base 16 (hexadecimal).
ios::showbase Display numeric constants in a format that can be read by the C++ compiler.
ios::showpoint Show decimal point and trailing zeros for floating-point values.
ios::uppercase Display uppercase A through F for hexadecimal values and E for scientific values.
ios::showpos Show plus signs (+) for positive values.
ios::scientific Display floating-point numbers in scientific format.
ios::fixed Display floating-point numbers in fixed format.
ios::unitbuf Cause ostream::osfx to flush the stream after each insertion. By default, cerr is unit buffered.
ios::stdio Cause ostream::osfx to flush stdout and stderr after each insertion.
This section shows how to control format and how to create insertion operators for your own classes. The insertion (<<) operator, which is preprogrammed for all standard C++ data types, sends bytes to an output stream object. Insertion operators work with predefined "manipulators," which are elements that change the default format of integer arguments.
To align output, you specify the output width for each item by placing the setw manipulator in the stream or by calling the width member function. This example right aligns the values in a column at least 10 characters wide:
#include <iostream.h>
void main()
{
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
for( int i = 0; i < 4; i++ )
{
cout.width(10);
cout << values[i] << '\n';
}
}
The output looks like this:
1.23
35.36
653.7
4358.24
Leading blanks are added to any value fewer than 10 characters wide.
To pad a field, use the fill member function, which sets the value of the padding character for fields that have a specified width. The default is a blank. To pad the column of numbers with asterisks, modify the previous for loop as follows:
for( int i = 0; i < 4; i++ )
{
cout.width( 10 );
cout.fill( '*' );
cout << values[i] << endl
}
The endl manipulator replaces the newline character (
'\n'
). The output looks like this:
******1.23
*****35.36
*****653.7
***4358.24
To specify widths for data elements in the same line, use the setw manipulator:
#include <iostream.h>
#include <iomanip.h>
void main()
{
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
for( int i = 0; i < 4; i++ )
cout << setw( 6 ) << names[i]
<< setw( 10 ) << values[i] << endl;
}
The width member function is declared in IOSTREAM.H. If you use setw or any other manipulator with arguments, you must include
IOMANIP.H. In the output, strings are printed in a field of width 6 and integers in a field of width 10: Zoot 1.23
Jimmy 35.36
Al 653.7
Stan 4358.24
Neither setw nor width truncates values. If formatted output exceeds the width, the entire value prints, subject to the stream’s precision setting. Both setw and width affect the following field only. Field width reverts to its default behavior (the necessary width) after one field has been printed. However, the other stream format options remain in effect until changed.
Output streams default to right-aligned text. To left align the names in the previous example and right align the numbers, replace the for loop as follows:
for ( int i = 0; i < 4; i++ )
cout << setiosflags( ios::left )
<< setw( 6 ) << names[i]
<< resetiosflags( ios::left )
<< setw( 10 ) << values[i] << endl;
The output looks like this:
Zoot 1.23
Jimmy 35.36
Al 653.7
Stan 4358.24
The left-align flag is set by using the
setiosflags manipulator with the ios::left enumerator. This enumerator is defined in the ios class, so its reference must include the ios:: prefix. The resetiosflags manipulator turns off the left-align flag. Unlike width and setw, the effect of setiosflags and resetiosflags is permanent.The default value for floating-point precision is six. For example, the number 3466.9768 prints as 3466.98. To change the way this value prints, use the
setprecision manipulator. The manipulator has two flags, ios::fixed and ios::scientific. If ios::fixed is set, the number prints as 3466.976800. If ios::scientific is set, it prints as 3.4669773+003.To display the floating-point numbers shown in
Alignment with one significant digit, replace the for loop as follows:for ( int i = 0; i < 4; i++ )
cout << setiosflags( ios::left )
<< setw( 6 )
<< names[i]
<< resetiosflags( ios::left )
<< setw( 10 )
<< setprecision( 1 )
<< values[i]
<< endl;
The program prints this list:
Zoot 1
Jimmy 4e+001
Al 7e+002
Stan 4e+003
To eliminate scientific notation, insert this statement before the for loop:
cout << setiosflags( ios::fixed );
With fixed notation, the program prints with one digit after the decimal point.
Zoot 1.2
Jimmy 35.4
Al 653.7
Stan 4358.2
If you change the ios::fixed flag to ios::scientific, the program prints this:
Zoot 1.2e+000
Jimmy 3.5e+001
Al 6.5e+002
Stan 4.4e+003
Again, the program prints one digit after the decimal point. If either ios::fixed or ios::scientific is set, the precision value determines the number of digits after the decimal point. If neither flag is set, the precision value determines the total number of significant digits. The resetiosflags manipulator clears these flags.
The dec, oct, and hex manipulators set the default radix for input and output. For example, if you insert the hex manipulator into the output stream, the object correctly translates the internal data representation of integers into a hexadecimal output format. The numbers are displayed with digits a through f in lowercase if the
ios::uppercase flag is clear (the default); otherwise, they are displayed in uppercase. The default radix is dec (decimal).