Introduction to Stream Manipulators
C++ provides various stream manipulators that perform formatting tasks. The stream manipulators provide capabilities such as setting field widths, setting precision, setting and unsetting format state, setting the fill character in fields, flushing streams, inserting a newline into the output stream (and flushing the stream), inserting a null character into the output stream and skipping white space in the input stream. These features are described in the following sections.
15.6.1. Integral Stream Base: dec, oct, hex and setbase
Integers are interpreted normally as decimal (base-10) values. To change the base in which integers are interpreted on a stream, insert the hex manipulator to set the base to hexadecimal (base 16) or insert the oct manipulator to set the base to octal (base 8). Insert the dec manipulator to reset the stream base to decimal.
The base of a stream also may be changed by the setbase stream manipulator, which takes one integer argument of 10, 8, or 16 to set the base to decimal, octal or hexadecimal, respectively. Because setbase takes an argument, it is called a parameterized stream manipulator. Using setbase (or any other parameterized manipulator) requires the inclusion of the header file. The stream base value remains the same until changed explicitly; setbase settings are "sticky." Figure 15.8 demonstrates stream manipulators hex, oct, dec and setbase.
Figure 15.8. Stream manipulators hex, oct, dec and setbase.
(This item is displayed on pages 782 - 783 in the print version)
1 // Fig. 15.8: Fig15_08.cpp 2 // Using stream manipulators hex, oct, dec and setbase. 3 #include 4 using std::cin; 5 using std::cout; 6 using std::dec; 7 using std::endl; 8 using std::hex; 9 using std::oct; 10 11 #include 12 using std::setbase; 13 14 int main() 15 { 16 int number; 17 18 cout << "Enter a decimal number: "; 19 cin >> number; // input number 20 21 // use hex stream manipulator to show hexadecimal number 22 cout << number << " in hexadecimal is: " << hex 23 << number << endl; 24 25 // use oct stream manipulator to show octal number 26 cout << dec << number << " in octal is: " 27 << oct << number << endl; 28 29 // use setbase stream manipulator to show decimal number 30 cout << setbase( 10 ) << number << " in decimal is: " 31 << number << endl; 32 return 0; 33 } // end main
|
15.6.2. Floating-Point Precision (precision, setprecision)
We can control the precision of floating-point numbers (i.e., the number of digits to the right of the decimal point) by using either the setprecision stream manipulator or the precision member function of ios_base. A call to either of these sets the precision for all subsequent output operations until the next precision-setting call. A call to member function precision with no argument returns the current precision setting (this is what you need to use so that you can restore the original precision eventually after a "sticky" setting is no longer needed). The program of Fig. 15.9 uses both member function precision (line 28) and the setprecision manipulator (line 37) to print a table that shows the square root of 2, with precision varying from 09.
Figure 15.9. Precision of floating-point values.
(This item is displayed on pages 783 - 784 in the print version)
1 // Fig. 15.9: Fig15_09.cpp 2 // Controlling precision of floating-point values. 3 #include 4 using std::cout; 5 using std::endl; 6 using std::fixed; 7 8 #include 9 using std::setprecision; 10 11 #include 12 using std::sqrt; // sqrt prototype 13 14 int main() 15 { 16 double root2 = sqrt( 2.0 ); // calculate square root of 2 17 int places; // precision, vary from 0-9 18 19 cout << "Square root of 2 with precisions 0-9." << endl 20 << "Precision set by ios_base member function " 21 << "precision:" << endl; 22 23 cout << fixed; // use fixed-point notation 24 25 // display square root using ios_base function precision 26 for ( places = 0; places <= 9; places++ ) 27 { 28 cout.precision( places ); 29 cout << root2 << endl; 30 } // end for 31 32 cout << " Precision set by stream manipulator " 33 << "setprecision:" << endl; 34 35 // set precision for each digit, then display square root 36 for ( places = 0; places <= 9; places++ ) 37 cout << set precision( places ) << root2 << endl; 38 39 return 0; 40 } // end main
|
15.6.3. Field Width (width, setw)
The width member function (of base class ios_base) sets the field width (i.e., the number of character positions in which a value should be output or the maximum number of characters that should be input) and returns the previous width. If values output are narrower than the field width, fill characters are inserted as padding. A value wider than the designated width will not be truncatedthe full number will be printed. The width function with no argument returns the current setting.
Common Programming Error 15.1
The width setting applies only for the next insertion or extraction (i.e., the width setting is not "sticky"); afterward, the width is set implicitly to 0 (i.e., input and output will be performed with default settings). Assuming that the width setting applies to all subsequent outputs is a logic error. |
Common Programming Error 15.2
When a field is not sufficiently wide to handle outputs, the outputs print as wide as necessary, which can yield confusing outputs. |
Figure 15.10 demonstrates the use of the width member function on both input and output. Note that, on input into a char array, a maximum of one fewer characters than the width will be read, because provision is made for the null character to be placed in the input string. Remember that stream extraction terminates when nonleading white space is encountered. The setw stream manipulator also may be used to set the field width.
Figure 15.10. width member function of class ios_base.
1 // Fig. 15.10: Fig15_10.cpp 2 // Demonstrating member function width. 3 #include 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 int widthValue = 4; 11 char sentence[ 10 ]; 12 13 cout << "Enter a sentence:" << endl; 14 cin.width( 5 ); // input only 5 characters from sentence 15 16 // set field width, then display characters based on that width 17 while ( cin >> sentence ) 18 { 19 cout.width( widthValue++ ); 20 cout << sentence << endl; 21 cin.width( 5 ); // input 5 more characters from sentence 22 } // end while 23 24 return 0; 25 } // end main
|
[Note: When prompted for input in Fig. 15.10, the user should enter a line of text and press Enter followed by end-of-file ( -z on Microsoft Windows systems, -d on UNIX and Macintosh systems).]
15.6.4. User-Defined Output Stream Manipulators
Programmers can create their own stream manipulators.[3] Figure 15.11 shows the creation and use of new nonparameterized stream manipulators bell (lines 1013), carriageReturn (lines 1619), tab (lines 2225) and endLine (lines 2932). For output stream manipulators, the return type and parameter must be of type ostream &. When line 37 inserts the endLine manipulator in the output stream, function endLine is called and line 31 outputs the escape sequence and the flush manipulator to the standard output stream cout. Similarly, when lines 3746 insert the manipulators tab, bell and carriageReturn in the output stream, their corresponding functionstab (line 22), bell (line 10) and carriageReturn (line 16) are called, which in turn output various escape sequences.
[3] Programmers also may create their own parameterized stream manipulatorsconsult your C++ compiler's documentation for instructions on how to do this.
Figure 15.11. User-defined, nonparameterized stream manipulators.
(This item is displayed on pages 786 - 787 in the print version)
1 // Fig. 15.11: Fig15_11.cpp 2 // Creating and testing user-defined, nonparameterized 3 // stream manipulators. 4 #include 5 using std::cout; 6 using std::flush; 7 using std::ostream; 8 9 // bell manipulator (using escape sequence a) 10 ostream& bell( ostream& output ) 11 { 12 return output << 'a'; // issue system beep 13 } // end bell manipulator 14 15 // carriageReturn manipulator (using escape sequence ) 16 ostream& carriageReturn( ostream& output ) 17 { 18 return output << ' '; // issue carriage return 19 } // end carriageReturn manipulator 20 21 // tab manipulator (using escape sequence ) 22 ostream& tab( ostream& output ) 23 { 24 return output << ' '; // issue tab 25 } // end tab manipulator 26 27 // endLine manipulator (using escape sequence and member 28 // function flush) 29 ostream& endLine( ostream& output ) 30 { 31 return output << ' ' << flush; // issue endl-like end of line 32 } // end endLine manipulator 33 34 int main() 35 { 36 // use tab and endLine manipulators 37 cout << "Testing the tab manipulator:" << endLine 38 << 'a' << tab << 'b' << tab << 'c' << endLine; 39 40 cout << "Testing the carriageReturn and bell manipulators:" 41 << endLine << ".........."; 42 43 cout << bell; // use bell manipulator 44 45 // use carriageReturn and endLine manipulators 46 cout << carriageReturn << "-----" << endLine; 47 return 0; 48 } // end main
|