Formatted I/O. McGraw-Hill The Complete Reference Fourth Edition
Anúncio
Anúncio
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
513
Standard C++ also defines these four additional streams: win, wout, werr, and
wlog
. These are wide-character versions of the standard streams. Wide characters are of type wchar_t and are generally 16-bit quantities. Wide characters are used to hold the large character sets associated with some human languages.
Formatted I/O
The C++ I/O system allows you to format I/O operations. For example, you can set a field width, specify a number base, or determine how many digits after the decimal point will be displayed. There are two related but conceptually different ways that you can format data. First, you can directly access members of the ios class. Specifically, you can set various format status flags defined inside the ios class or call various ios member functions. Second, you can use special functions called manipulators that can be included as part of an I/O expression.
We will begin the discussion of formatted I/O by using the ios member functions and flags.
Formatting Using the ios Members
Each stream has associated with it a set of format flags that control the way information is formatted. The ios class declares a bitmask enumeration called fmtflags in which the following values are defined. (Technically, these values are defined within ios_base, which, as explained earlier, is a base class for ios.) adjustfield fixed left showbase unitbuf basefield floatfield oct showpoint uppercase boolalpha hex right showpos dec internal scientific skipws
These values are used to set or clear the format flags. If you are using an older compiler, it may not define the fmtflags enumeration type. In this case, the format flags will be encoded into a long integer.
When the skipws flag is set, leading white-space characters (spaces, tabs, and newlines) are discarded when performing input on a stream. When skipws is cleared, white-space characters are not discarded.
When the left flag is set, output is left justified. When right is set, output is right justified. When the internal flag is set, a numeric value is padded to fill a field by inserting spaces between any sign or base character. If none of these flags are set, output is right justified by default.
514
C + + : T h e C o m p l e t e R e f e r e n c e
By default, numeric values are output in decimal. However, it is possible to change the number base. Setting the oct flag causes output to be displayed in octal. Setting the
hex
flag causes output to be displayed in hexadecimal. To return output to decimal, set the dec flag.
Setting showbase causes the base of numeric values to be shown. For example, if the conversion base is hexadecimal, the value 1F will be displayed as 0x1F.
By default, when scientific notation is displayed, the e is in lowercase. Also, when a hexadecimal value is displayed, the x is in lowercase. When uppercase is set, these characters are displayed in uppercase.
Setting showpos causes a leading plus sign to be displayed before positive values.
Setting showpoint causes a decimal point and trailing zeros to be displayed for all floating-point output—whether needed or not.
By setting the scientific flag, floating-point numeric values are displayed using scientific notation. When fixed is set, floating-point values are displayed using normal notation. When neither flag is set, the compiler chooses an appropriate method.
When unitbuf is set, the buffer is flushed after each insertion operation.
When boolalpha is set, Booleans can be input or output using the keywords true and false.
Since it is common to refer to the oct, dec, and hex fields, they can be collectively referred to as basefield. Similarly, the left, right, and internal fields can be referred to as adjustfield. Finally, the scientific and fixed fields can be referenced as floatfield.
Setting the Format Flags
To set a flag, use the setf( ) function. This function is a member of ios. Its most common form is shown here: fmtflags setf(fmtflags flags);
This function returns the previous settings of the format flags and turns on those flags specified by flags. For example, to turn on the showpos flag, you can use this statement: stream.setf(ios::showpos);
Here, stream is the stream you wish to affect. Notice the use of ios:: to qualify showpos.
Since showpos is an enumerated constant defined by the ios class, it must be qualified by ios when it is used.
The following program displays the value 100 with the showpos and showpoint flags turned on.
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
515
#include <iostream> using namespace std; int main()
{ cout.setf(ios::showpoint); cout.setf(ios::showpos); cout << 100.0; // displays +100.000
} return 0;
It is important to understand that setf( ) is a member function of the ios class and affects streams created by that class. Therefore, any call to setf( ) is done relative to a specific stream. There is no concept of calling setf( ) by itself. Put differently, there is no concept in C++ of global format status. Each stream maintains its own format status information individually.
Although there is nothing technically wrong with the preceding program, there is a more efficient way to write it. Instead of making multiple calls to setf( ), you can simply OR together the values of the flags you want set. For example, this single call accomplishes the same thing:
// You can OR together two or more flags, cout.setf(ios::showpoint | ios::showpos);
Because the format flags are defined within the ios class, you must access their values by using ios and the scope resolution operator. For example, showbase by itself will not be recognized. You must specify ios::showbase.
Clearing Format Flags
The complement of setf( ) is unsetf( ). This member function of ios is used to clear one or more format flags. Its general form is void unsetf(fmtflags flags);
The flags specified by flags are cleared. (All other flags are unaffected.)
The following program illustrates unsetf( ). It first sets both the uppercase and
scientific
flags. It then outputs 100.12 in scientific notation. In this case, the "E" used
516
C + + : T h e C o m p l e t e R e f e r e n c e in the scientific notation is in uppercase. Next, it clears the uppercase flag and again outputs 100.12 in scientific notation, using a lowercase "e."
#include <iostream> using namespace std; int main()
{ cout.setf(ios::uppercase | ios::scientific); cout << 100.12; // displays 1.001200E+02 cout.unsetf(ios::uppercase); // clear uppercase cout << " \n" << 100.12; // displays 1.001200e+02
} return 0;
An Overloaded Form of setf( )
There is an overloaded form of setf( ) that takes this general form: fmtflags setf(fmtflags flags1, fmtflags flags2);
In this version, only the flags specified by flags2 are affected. They are first cleared and then set according to the flags specified by flags1. Note that even if flags1 contains other flags, only those specified by flags2 will be affected. The previous flags setting is returned.
For example,
#include <iostream> using namespace std; int main( )
{ cout.setf(ios::showpoint | ios::showpos, ios::showpoint); cout << 100.0; // displays 100.000, not +100.000
} return 0;
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
517
Here, showpoint is set, but not showpos, since it is not specified in the second parameter.
Perhaps the most common use of the two-parameter form of setf( ) is when setting the number base, justification, and format flags. As explained, references to the oct,
dec
, and hex fields can collectively be referred to as basefield. Similarly, the left, right, and internal fields can be referred to as adjustfield. Finally, the scientific and fixed fields can be referenced as floatfield. Since the flags that comprise these groupings are mutually exclusive, you may need to turn off one flag when setting another. For example, the following program sets output to hexadecimal. To output in hexadecimal, some implementations require that the other number base flags be turned off in addition to turning on the hex flag. This is most easily accomplished using the two-parameter form of setf( ).
#include <iostream> using namespace std; int main()
{ cout.setf(ios::hex, ios::basefield); cout << 100; // this displays 64
} return 0;
Here, the basefield flags (i.,e., dec, oct, and hex) are first cleared and then the hex flag is set.
Remember, only the flags specified in flags2 can be affected by flags specified by
flags1. For example, in this program, the first attempt to set the showpos flag fails.
// This program will not work.
#include <iostream> using namespace std; int main()
{ cout.setf(ios::showpos, ios::hex); // error, showpos not set cout << 100 << '\n'; // displays 100, not +100 cout.setf(ios::showpos, ios::showpos); // this is correct
518
C + + : T h e C o m p l e t e R e f e r e n c e cout << 100; // now displays +100
} return 0;
Keep in mind that most of the time you will want to use unsetf( ) to clear flags and the single parameter version of setf( ) (described earlier) to set flags. The setf(fmtflags,
fmtflags)
version of setf( ) is most often used in specialized situations, such as setting the number base. Another good use may involve a situation in which you are using a flag template that specifies the state of all format flags but wish to alter only one or two. In this case, you could specify the template in flags1 and use flags2 to specify which of those flags will be affected.
Examining the Formatting Flags
There will be times when you only want to know the current format settings but not alter any. To accomplish this goal, ios includes the member function flags( ), which simply returns the current setting of each format flag. Its prototype is shown here: fmtflags flags( );
The following program uses flags( ) to display the setting of the format flags relative to cout. Pay special attention to the showflags( ) function. You might find it useful in programs you write.
#include <iostream> using namespace std; void showflags() ; int main()
{
// show default condition of format flags showflags(); cout.setf(ios::right | ios::showpoint | ios::fixed); showflags();
} return 0;
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
519
// This function displays the status of the format flags.
void showflags()
{ ios::fmtflags f; long i; f = (long) cout.flags(); // get flag settings
// check each flag for(i=0x4000; i; i = i >> 1) if(i & f) cout << "1 "; else cout << "0 ";
} cout << " \n";
Sample output from the program is shown here. (The precise output will vary from compiler to compiler.)
0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 1 0 1 0 0 1 0 0 0 1
Setting All Flags
The flags( ) function has a second form that allows you to set all format flags associated with a stream. The prototype for this version of flags( ) is shown here: fmtflags flags(fmtflags f);
When you use this version, the bit pattern found in f is used to set the format flags associated with the stream. Thus, all format flags are affected. The function returns the previous settings.
The next program illustrates this version of flags( ). It first constructs a flag mask that turns on showpos, showbase, oct, and right. All other flags are off. It then uses
flags( )
to set the format flags associated with cout to these settings. The function
showflags( )
verifies that the flags are set as indicated. (It is the same function used in the previous program.)
#include <iostream> using namespace std;
520
C + + : T h e C o m p l e t e R e f e r e n c e void showflags(); int main()
{
// show default condition of format flags showflags();
// showpos, showbase, oct, right are on, others off ios::fmtflags f = ios::showpos | ios::showbase | ios::oct | ios::right; cout.flags(f); // set all flags showflags();
} return 0;
Using width( ), precision( ), and fill( )
In addition to the formatting flags, there are three member functions defined by ios that set these format parameters: the field width, the precision, and the fill character.
The functions that do these things are width( ), precision( ), and fill( ), respectively.
Each is examined in turn.
By default, when a value is output, it occupies only as much space as the number of characters it takes to display it. However, you can specify a minimum field width by using the width( ) function. Its prototype is shown here: streamsize width(streamsize w);
Here, w becomes the field width, and the previous field width is returned. In some implementations, the field width must be set before each output. If it isn't, the default field width is used. The streamsize type is defined as some form of integer by the compiler.
After you set a minimum field width, when a value uses less than the specified width, the field will be padded with the current fill character (space, by default) to reach the field width. If the size of the value exceeds the minimum field width, the field will be overrun. No values are truncated.
When outputting floating-point values, you can determine the number of digits of precision by using the precision( ) function. Its prototype is shown here: streamsize precision(streamsize p);
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
521
Here, the precision is set to p, and the old value is returned. The default precision is 6.
In some implementations, the precision must be set before each floating-point output.
If it is not, then the default precision will be used.
By default, when a field needs to be filled, it is filled with spaces. You can specify the fill character by using the fill( ) function. Its prototype is char fill(char ch);
After a call to fill( ), ch becomes the new fill character, and the old one is returned.
Here is a program that illustrates these functions:
#include <iostream> using namespace std; int main()
{ cout.precision(4) ; cout.width(10); cout << 10.12345 << "\n"; // displays 10.12
cout.fill('*'); cout.width(10); cout << 10.12345 << "\n"; // displays *****10.12
// field width applies to strings, too cout.width(10); cout << "Hi!" << "\n"; // displays *******Hi!
cout.width(10); cout.setf(ios::left); // left justify cout << 10.12345; // displays 10.12*****
} return 0;
This program's output is shown here:
10.12
*****10.12
*******Hi!
10.12*****
522
C + + : T h e C o m p l e t e R e f e r e n c e
There are overloaded forms of width( ), precision( ), and fill( ) that obtain but do not change the current setting. These forms are shown here: char fill( ); streamsize width( ); streamsize precision( );
Using Manipulators to Format I/O
The second way you can alter the format parameters of a stream is through the use of special functions called manipulators that can be included in an I/O expression. The standard manipulators are shown in Table 20-1. As you can see by examining the table, many of the I/O manipulators parallel member functions of the ios class. Many of the manipulators were added recently to C++ and will not be supported by older compilers.
Manipulator boolalpha dec endl ends fixed flush hex internal left nobooalpha noshowbase noshowpoint noshowpos
Table 20-1.
The C++ Manipulators
Purpose
Turns on boolapha flag.
Turns on dec flag.
Output a newline character and flush the stream.
Output a null.
Turns on fixed flag.
Flush a stream.
Turns on hex flag.
Turns on internal flag.
Turns on left flag.
Turns off boolalpha flag.
Turns off showbase flag.
Turns off showpoint flag.
Turns off showpos flag.
Input/Output
Input/Output
Input/Output
Output
Output
Output
Output
Input/Output
Output
Output
Input/Output
Output
Output
Output
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
523
Manipulator Purpose noskipws nounitbuf nouppercase oct
Turns off skipws flag.
Turns off unitbuf flag.
Turns off uppercase flag.
Turns on oct flag.
resetiosflags (fmtflags f ) Turn off the flags specified in f. right scientific setbase(int base) setfill(int ch) setiosflags(fmtflags f )
Turns on right flag.
Turns on scientific flag.
Set the number base to base.
Set the fill character to ch. setprecision (int p)
Turn on the flags specified in f.
Set the number of digits of precision.
setw(int w) showbase showpoint showpos skipws unitbuf uppercase ws
Set the field width to w.
Turns on showbase flag.
Turns on showpoint flag.
Turns on showpos flag.
Turns on skipws flag.
Turns on unitbuf flag.
Turns on uppercase flag.
Skip leading white space.
Table 20-1.
The C++ Manipulators ( continued )
Input/Output
Input
Output
Output
Input/Output
Input/Output
Output
Output
Input/Output
Output
Input/output
Output
Output
Output
Output
Output
Input
Output
Output
Input
To access manipulators that take parameters (such as setw( )), you must include
<iomanip>
in your program.
524
C + + : T h e C o m p l e t e R e f e r e n c e
Here is an example that uses some manipulators:
#include <iostream>
#include <iomanip> using namespace std; int main()
{ cout << hex << 100 << endl; cout << setfill('?') << setw(10) << 2343.0;
} return 0;
This displays
64
??????2343
Notice how the manipulators occur within a larger I/O expression. Also notice that when a manipulator does not take an argument, such as endl( ) in the example, it is not followed by parentheses. This is because it is the address of the function that is passed to the overloaded << operator.
As a comparison, here is a functionally equivalent version of the preceding program that uses ios member functions to achieve the same results:
#include <iostream>
#include <iomanip> using namespace std; int main()
{ cout.setf(ios::hex, ios::basefield); cout << 100 << "\n"; // 100 in hex cout.fill('?'); cout.width(10); cout << 2343.0;
} return 0;
C h a p t e r 2 0 : T h e C + + I / O S y s t e m B a s i c s
525
As the examples suggest, the main advantage of using manipulators instead of the ios member functions is that they often allow more compact code to be written.
You can use the setiosflags( ) manipulator to directly set the various format flags related to a stream. For example, this program uses setiosflags( ) to set the showbase and showpos flags:
#include <iostream>
#include <iomanip> using namespace std; int main()
{ cout << setiosflags(ios::showpos); cout << setiosflags(ios::showbase); cout << 123 << " " << hex << 123;
} return 0;
The manipulator setiosflags( ) performs the same function as the member function
setf( )
.
One of the more interesting manipulators is boolapha. It allows true and false values to be input and output using the words "true" and "false" rather than numbers.
For example,
#include <iostream> using namespace std; int main()
{ bool b; b = true; cout << b << " " << boolalpha << b << endl; cout << "Enter a Boolean value: "; cin >> boolalpha >> b; cout << "Here is what you entered: " << b;
} return 0;
Download
Anúncio