C++输出格式控制


11.7 流格式状态
各种格式标志指定了在I/O流中执行的格式类型。成员函数serf、unserf和flag控制标志的设置。


11.7.1 格式状态标志
图11.20中的格式状态标志在类ios中被定义为枚举值,留到下几节解释。
虽然成员函数flags、serf和unseff可以控制这些标志,但是许多C++程序员更喜欢使用流操纵算子(见11.7.8节)。程序员可以用按位或操作(|)把各种标志选项结合在一个long类型的值中(见图11.23)。调用成员函数flags并指定要进行或操作的标志选项就可以在流中设置这些标志,并返回一个包含以前标志选项的long类型的值。返回值通常要保存起来,以便用保存值调用flags来恢复以前的流选项。
flags函数必须指定一个代表所有标志设置的值。而带有一个参数的函数setf可指定一个或多个要进行或操作的标志,并把它们与现存的标志设置相“或”,形成新的格式状态。
参数化的流操纵算子setiosflags与成员函数serf执行同样的功能。流操纵算子resetiosflags与成员函数unsetf执行同样的功能。不论使用哪一种流操纵算子,在程序中都必须包含头文件iomanip.h。
skipws标志指示>>跳过输人流中的空白字符。>>的默认行为是跳过空白字符,调用unsetf(ios::skipws)可改变默认行为。流操纵算子ws也可用于指定跳过流中的空白字符。
----------------------------------------------------------------------------------------------
格式状态 说明
----------------------------------------------------------------------------------------------
ios::skipws 跳过输入流中的空白字符
ios::left 在域中左对齐输出,必要时在右边显示填充字符
ios:right 在域中右对齐输出,必要时在左边显示填充字符
ios::internal 表示数字的符号应在域中左对齐,而数字值应在域中右对齐(即在符号和数字之间填充字符
ios::dec 指定整数应作为十进制(基数10)值
ios::oct 指定整数应作为八进制(基数8)值
ios::hex 指定整数应作为十六进制(基数16)值
ios::showbase 指定在数字疥面输出进制(0表示八进制,0x或0X表示十六进制)
ios::showpoint 指定浮点数输出时应带小数点。这通常和ios::fixed一起使用保证小数点后面有一定位数
ios::uppercase 指定表示十六进制Rx应为大写,表示浮点科学计数法的e应为大写
ios::showpos 指定正数和负数前面分别加上正号或-号
ios::scientific 指事实上浮点数输出采用科学计数法
ios::fixed 指事实上浮点数输出采用定点符号,保证小数点后面有一定位数


-----------------------------------------------------------------------------------------------


                  图 11.20 格式状态标志


11.7.2 尾数零和十进制小数点(ios::showpoint)
设置showpoint标志是为了强制输出浮点数的小数点和尾数零。若没有设置showpoint,浮点数79.0将被打印为79,否则打印为79.000000(或由当前精度指定的尾数零的个数)。图11.21中的程序用成员函数setf设置showpoint标志,从而控制了浮点数的尾数零和小数点的输出。
i // Fig. 11.21: fig11_21.cpp
2 // Controlling the printing of trailing zeros and decimal
3 // points for floating-point values.
4 #include <iostream.h>
5 #include <iomanip.h>
6 #include <math.h>
7
8 int main()
9 {
10 cout << "Before setting the ios::showpoint flag\n"
11 << "9.9900 prints as: "<< 9.9900
12 << "\n9.9000 prints as: "<< 9.9000
13 << "\n9.0000 prints as: "<< 9.0000
14 << "\n\nAfter setting the ios::showpoint flag\n";
15 cout.setf( ios::showpoint );
16 cout << "9.9900 prints as: "<< 9.9900
17 << "\n9.90O0 prints as: "<< 9.9000
18 << "\n9.0000 prints as: "<< 9.0000 << endl;
19 return 0;
2O }


输出结果:
Before setting the ios::showpolnt flag
9.9900 prints as: 9.99
9.9000 prints as: 9.9
9.9000 prints as: 9


After setting the ios::showpoint flag
9.9900 prints as: 9.99000
9.9000 prints as: 9.90000
9.0000 prints as: 9.00000


               图 11.21 控制浮点数的尾数零和小数点的输出


11.7.3 对齐(ios::left、ios::right、ios::internal)
left标志可以使输出域左对齐并把填充字符放在输出数据的右边,right标志可以使输出域右对齐并把填充字符放在输出数据的左边。填充的字符由成员函数fill或参数化的流操纵算子setfill指定(见7.4节)。图11.22用流操纵算子setw、setiosflags、reseticsfiags以及成员函数serf和unsetf控制整数值在域宽内左对齐和右对齐。
1 // Fig. 11.22: fig11_22.cpp
2 // Left-justification and right-justification.
3 #include <iostream.h>
4 #include <iomanip.h>
6 int main()
7{
8 int x = 12345;
9
10 cout << "Default is right justified:\n"
11 << setw(10) << x << "\n\nUSING MEMBER FUNCTIONS"
12 << "\nUse serf to set ios::left:\n" << setw(10);
13
14 cout.setf( ios::left, ios::adjustfield );
15 cout << x << "\nUse unsetf to restore default:\n";
16 cout.unsetf( ios::left );
17 cout << setw( 10 ) << x
18 << "\n\nUSING PARAMETERIZED STREAM MANIPUAATORS"
19 << "\nUse setiosflags to set ios::left:\n"
20 << setw( 10 ) << setiosflags( ios::left ) << x
21 << "\nUse resetiosflags to restore default:\n"
22 << setw( 10 ) << resetiosflags( ios::left )
23 << x << endl;
24 return 0;
25 }


输出结果:
Default is right justified:
12345
USING MEMBER FUNCTIONS
Use setf to set ios::left:
12345
Use unsetf to restore default:
12345
USING PARAMETERIZED STREAM MANIPULATORS
Use setiosflags to set ios::left:
12345
Use resetiosflags to restore default:
12345

图 11.22 左对齐和右对齐


internal标志指示将一个数的符号位(设置了ios::showbase标志时为基数,见11.7.5节)在域宽内左对齐,数值右对齐,中间的空白由填充字符填充。left、right和internal标志包含在静态数据成员ios::adjustfield中。在设置left、right和internal对齐标志时,setf的第二个参数必须是ios::adjustfield,这样才能使serf只设置其中一个标志(这三个标志是互斥的)。图11.23中的程序用流操纵算子setiosflags和setw指定中间的空白。注意,ios::showpos标志强制打印了加号。
1 // Fig. 11.23: figll_23.cpp
2 // Printing an integer with internal spacing and
3 // forcing the plus sign.
4 #include <iostream.h>
5 #include <iomanip.h>
6
7 int main()
8 {
9 cout << setiosflags( ios::internal | ios::showpos )
10 << setw( 10 ) << 123 << endl;
11 return O;
12 }


输出结果:
+ 123


图 11.23 打印中间带空白的整数并强制输出加号


11.7.4 设置填充字符(fill、setfill)
成员函数fill设置用于使输出域对齐的填充字符,如果不特别指定,空格即为填充字符。fill函数返回以前设置的填充字符。图11.24中的程序演示了使用成员函数fill和流操纵算子,setfill来控制填充字符的设置和清除。
1 // Fig. 11.24: fig11_24.cpp
2 // Using the fill member function and the setfill
3 // manipulator to change the padding character for
4 // fields larger than the values being printed.
5 #include <iostream.h>
6 finclude <iomanip.h>
7
8 int main()
9 {
10 int x = 10000;
11
12 cout << x << "printed as iht right and left justified\n"
13 << "and as hex with internal justification.\n"
14 << "Using the default pad character (space):\n";
15 cout.setf( ios::showbase );
16 cout << setw( 10 ) << x << '\n';
17 cout.setf( ios::left, ios::adjustfield );
18 cout << setw( 10 } << x << '\n';
19 cout.serf( ios::internal, ios::adjustfield );
20 cout << setw( 10 ) << hex << x;
21
22 cout << "\n\nUsing various padding characters:\n";
23 cout.setf( ios::right, ios::adjustfield );
24 cout.fill( '*' );
25 cout << setw( 10 ) << dec << x << '\n';
26 cout.setf( ios::left, ios::adjustfield );
27 cout << setw( 10 ) << setfill( '%' ) << x << '\n';
28 cout.setf( ios::internal, ios::adjustfield );
29 cout << setw( 10 ) << setfill( '^' ) << hex << x << endl;
30 return 0;
31 }


输出结果:
10000 printed as int right and left justified
and as hex with internal justification.
Using the default pad character (space):
l0000
10000


0x2710


Using various padding characters:
*****10000
10000%%%%%


图 11.24 用fill和setfill为实际宽度小于域宽的数据改变填充字符


11.7.5 整数流的基数:(ios::dec、ios::oct、ios::hex、ios::showbase)
静态成员ios::basefield(在setf中的用法与ios::adjustfield类似)包括ios::oct、ios::hex和ios::dec标志位,这些标志位分别指定把整数作为八进制、十六进制和十进制值处理。如果没有设置这些位,则流插入运算默认整数为十进制数,流读取运算按整数提供的方式处理数据(即以零打头的整数按八进制数处理,以0x或0X打头的按十六进制数处理,其他所有整数都按十进制数处理)。一旦为流指定了特定的基数,流中的所有整数都按该基数处理,直到指定了新的基数或程序结束为止。
设置showbase标志可强制输出整数值的基数。十进制数以通常方式输出,输出的八进制数以0打头,输出的十六进制数以0x或OX打头(由uppercase标志决定是0x还是0X,见11.7.7节)。图11.25中的程序用showbase标志强制整数按十进制、八进制和十六进制格式打印。
1 // Fig. 11.25: figll_25.cpp
2 // Using the ios::showbase flag
3 #include <iostream.h>
4 #include <iomanip.h>
5
6 int main()
7 {
8 int x = 100;
9
10 cout << setiosflags( ios::showbase )
11 << "Printing integers preceded by their base:\n"
12 << x << '\n'
13 << oct << x << '\n'
14 << hex << x << endl;
15 return 0;
16 }


输入结果:
Printing integers preceded by their base:
I00
0144
0x64


图 11.25 使用ios::showbase标志


11.7.6 浮点数和科学记数法(ios::scientific、ios::fixed)
ios::scientific和ios::fixed标志包含在静态数据成员ios::floatfield中(在setf中的用法与ios:: adjustfield和ios::basefield类似)。这些标志用于控制浮点数的输出格式。设置scientific标志使浮点数按科学记数法输出,设置fixed标志使浮点数按照定点格式输出,即显示出小数点,小数点后边
有指定的位数(由成员函数precision指定)。若没有这些设置,则浮点数的值决定输出格式。
调用cout.setf(O,ios::floatfield)恢复输出浮点数的系统默认格式。图11.26中的程序示范了以定点格式和科学记数法显示的浮点数。
1 // Fig. 11.26: flg11_26.cpp
2 // Displaying floating-point values in system default,
3 // scientific, and fixed formats.
4 #include <iostream.h>
5
6 int main()
7 {
8 double x = .001239567, y = 1.946e9;
9
10 cout << "Displayed in default format:\n"
11 << x << '\t' << y << '\n';
12 cout.setf( ios::scientific, ios::floatfield );
13 cout << "Displayed in scientific format:\n"
14 << x << '\t' << y << '\n';
15 cout.unsetf( ios::scientific );
16 cout << "Displayed in default format after unsetf:\n"
17 << x << ,\t' << y << ,\n,;
18 cout.setf( ios::fixed, ios::floatfield );
19 cout << "Displayed in fixed format:\n"
20 << x << '\t' << y << endl;
21 return 0;
22 }


输出结果:
Displayed in default format:
0.00123457 1.946e+009
Displayed in scientific format:
1.234567e-003 1.946000e+009
Displayed in default format after unsetf:
0.00123457 1.946e+009
Displayed in fixed format:
0.001235 1946000000.000000


图 11.26 以系统默认格式、科学计数法和定点格式显示浮点数


11.7.7 大/小写控制(ios::upercase)
设置ios::uppercase标志用来使大写的X和E分别同十六进制整数和以科学记数法表示的浮点数一起输出(见图11.27)一旦设置ios::uppercase标志,十六进制数中的所有字母都转换成大写。
1 // Fig. 11.27: fig11_27.cpp
2 // Using the ios::uppercase flag
3 #include <iostream.h>
4 #include <iomanip.h>
5
6 int main()
7 {
8 cout << setiosflags( ios::uppercase )
9 << "Printing uppercase letters in scientific\n"
10 << "notation exponents and hexadecimal values:\n"
11 << 4.345e10 << '\n' << hex << 123456789 << endl;
12 return O;
13 }


输出结果:
Printing uppercase letters in scientific
notation exponents and hexadecimal values:
4.395E+010
75BCD16


图 11.27 使用ios::uppercase标志


11.7.8 设置及清除格式标志(flags、setiosflags、resetosflags)
无参数的成员函数flags只返回格式标志的当前设置(long类型的值)。带一个long类型参数的成员函数flags按参数指定的格式设置标志,返回以前的标志设置。flags的参数中未指定的任何格式都会被清除。图11.18的程序用成员函数flags设置新的格式状态和保存以前的格式状态,然后恢复原来的格式设置。
1 // Fig. 11.28: fig11_28.cpp
2 // Demonstrating the flags member function.
3 #include <iostream.h>
4
5 int main()
6 {
7 int i = 1000;
8 double d = 0.0947625;
9
10 cout << "The value of the flags variable is:"
11 << cout.flags()
12 << "\nPrint int and double in original format:\n"
13 << i << '\t' << d << "\n\n";
14 long originalFormat =
15 cout.flags( ios::oct | ios::scientific );
16 cout << "The value of the flags variable is:"
17 << cout.flags()
18 << "\nPrint int and double in a new format\n"
19 << "specified using the flags member function:\n"
20 << i << '\t' << d << "\n\n";
21 cout.flags( originalFormat );
22 cout << "The value of the flags variable is:"
23 << cout.flags()
24 << "\nPrint values in original format again:\n"
25 << i << '\t' << d << endl;
26 return 0;
27 }


输出结果:
The value of the flags variable is: 0
Print int and double in original format:
1000 0.0947628


The value of the flags variable is: 4040
Print iht and double in a new format
Specified using the flags member function:
1750 9.476280e-002


The value of the flags variable is: 0
Print values in original format again:
1000 0.0947628


图 11.28 演示成员函数flags


成员函数serf设置参数所指定的格式标志,并返回long类型的标志设置值,例如:
long previousFlagSettings=
cout.setf(ios::showpoint | ios::showpos);
带两个long型参数的setf成员函数.例如:
cout.setf(ios::left,ios::adjustfield);
首先清除ios::adjustfield位,然后设置ios::left标志。该版本的setf用于与ios::basefield(用ios::dec、
ios::oct和ios::hex表示)、ios::floatfield(用ios::scientific和ios::fixed表示)和ios::adjustfiald(用ios::
left、ios::right和ios::internal表示)相关的位段。
成员函数unsetf清除指定的标志并返回清除前的标志值。


11.8 流错误状态
可以用类ios中的位测试流的状态。类ios是输入/输出类istream、ostream和iostream的基类。
当遇到文件结束符时,输人流中自动设置eofbit。可以在程序中使用成员函数eof确定是否已经到达文件尾。如果cin遇到了文件结束符,那么函数调用:
cin.eof()
返回true,否则返回false。
当流中发生格式错误时,虽然会设置failbit,但是字符并末丢失。成员函数fail判断流操作是否失败,这种错误通常可修复。
当发生导致数据丢失的错误时,设置badbit。成员函数bad判断流操作是否失败,这种严重错误通常不可修复。
如果eofbit、failbit或badbit都没有设置,则设置goodbit。
如果函数bad、fail和eof全都返回false,则成员函数good返回true。程序中应该只对“好”的流进行I/O操作。
成员函数rdstate返回流的错误状态。例如.函数调用cout.rdstate将返回流的状态,随后可以用一条switch语句测试该状态,测试工作包括检查ios::eofbit、ios::badbit、ios::failbit和ios::goodbit。
测试流状态的较好方法是使用成员函数eof、bad、fail和good,使用这些函数不需要程序员熟知特定的状态位。
成员函数clear通常用于把—个流的状态恢复为“好”,从而可以对该流继续执行I/O操作。由于clear的默认参数为ios::goodbit,所以下列语句:
cin.clear();
清除cin,并为流设置goodbit。下列语句:
cin.clear(ios::failbit)
实际上给流设置了failbit。在用自定义类型对cin执行输入操作或遇到问题时,用户可能需要这么做。clear这个名字用在这里似乎并不合适,但规定就是如此。
图11.29中的程序演示了成员函数rdstate、eof、fail、bad、good和clear的使用。
只要badbit和failbit中有一个被置位,成员函数operator!就返回true。只要badbit和failbit中有一个被置位,成员函数operator void*就返回false。这些函数可用于文件处理过程中测试选择结构或循环结构条件的true/false情况。


1 // Fig. 11.29: fig11_29.cpp
2 // Testing error states.
3 #include <iostream.h>
4
5 int main()
6 {
7 int x;
8 cout << "Before a bad input operation:"
9 << "\ncin.rdstate(): " << cin.rdstate()
10 << "\n cin.eof(): "<< cin.eof()
11 << "In cin.fail(): "<< cin.fail()
12 << "\n cin.bad(): " << cin.bad()
13 << "\n cin.good(): "<< cin.good()
14 << "\n\nExpects an integer, but enter a character: ";
15 cin >> x;
16
17 cout << "\nEnter a bad input operation:"
18 << "\ncin.rdstate(): "<< cin.rdstate()
19 << "\n cin.eof(): "<< cin.eof()
20 << "\n cin.fail(): " << cin.fail()
21 << "\n cin.bad(): "<< cin.badO
22 << "\n cin.geed() " << cin.good() << "\n\n";
23
24 cin.clear();
25
26 cout << "After cin.clear()"
27 << "\ncin.fail(): "<< cin.fail()
28 << "\ncin.good(): "<< cin.good{) << endl;
29 return 0;
30 }


输出结果:
Before a bad input operation:
cin.rdstate(): 0
cin.eof(): 0
cin.fail() 0
tin.bad(): 0
cin.good(): 0


Expects an integer, but enter a character: A


After a bad input operation:
cin.eof(): 0
cin.fail(): 2
cin.bad(): 0
cin.good(): 0


After cin.clear()
cin. fail():0
cin.good(): 1


图 11.29 测试错误状态




11.9 把输出流连到输入流上
交互式应用程序通常要分别用类istream和ostream输入和输出数据。当提示信息出现在屏幕上时,用户输入一个数据来响应。显然,提示信息必须在执行输入操作前出现。在有输出缓冲区的情况下,只有在缓冲区已满时、在程序中明确地刷新输出缓冲区时或因程序结束而自动刷新输出缓冲区时,输出信息才会显示到屏幕上。为保证输出要在下一个输入前显示,C++提供了成员函数tie,该函数可以实现输入/输出操作的同步,也就是把这两个操作“系在一起”。例如,函数调用:
cin.tie(&cout);
把cout(ostream的对象)连到cin(istream的对象)上。实际上,C++为了建立用户的标准输入/输出环境而自动执行了这个操作,所以这个专门的调用其实是多余的。但是,用户可以显式地把其他配对的输入/输出流“系”在一起。使用函数调用:
inputStream.tie(0);
可以从一个输出流中解开输入流inputStream。




小 结


●I/O操作是以对数据类型敏感的方式执行的。
C++的I/O操作是以字节流的形式实现的。流实际上就是字节序列。
●输入/输出系统的任务实际上就是以一种稳定、可靠的方式在设备与内存之间传输数据。
●C++提供了低级和高级I/O功能。低级I/O功能通常只在设备和内存之间传输一些字节。高级I/O功能把若干个字节组合成有意义的单位,如整数、浮点数、字符、字符串以及用户自定义类型的数据。
●C++提供了无格式I/O和格式化I/O两种操作。无格式I/O传输速度快,但使用起来较为麻烦。格式化I/O按不同的类型对数据进行处理,但需要增加额外的处理时间,不适于处理大容量的数据传输。
●头文件iostream.h包括了操作所有输入/输出流所需的基本信息,因此在大多数C++程序中都应该包含这个头文件。
●在执行格式化I/O时,如果流中带有含参数的流操纵算子,头文件iomanip.h所包含的信息是有用的。
●头文件fstream.h包含了文件处理操作所需的信息。
●类istream支持流的输入操作。
●类ostream支持流的输出操作。
●类iostream同时支持流的输入、输出操作。
●类istream和ostream是通过单一继承从基类ios派生出来的。
●类iostream是通过多重继承从类istream和ostream派生出来的。
●重载的左移位运算符(<<)表示流的输出,称为流插入运算符。
●重载的右移位运算符(>>)表示流的输入,称为流读取运算符。
●cin是类istream的对象,它与标准输人设备(通常指键盘)“连”在一起。
●cout是类ostream的对象,它与标准输出设备(通常指显示器)“连”在一起。
●cerr是类ostream的对象,它与标准错误输出设备“连”在一起。对象cerr的输出是非缓冲输出,每一条出错信息都 会被立即显示出来。
●流操纵算子endl用来插入一个换行符,并同时刷新输出缓冲区。
●C++编译器能够自动识别输入、输出数据的类型。
●默认情况下,地址是以十六进制格式显示的。
●可以将指针强制转换为void*类型从而输出指针变量中的地址。
●成员函数put用于输出单个字符,可以连续调用pul函数。
●流的输入通过流读取运算符>>实现,该运算符自动跳过输入流中的空白字符。
●当遇到输入流中的文件结束符时,运算符>>返回false。
●当输入出现格式错误时,流读取运算符就会设置输入流的failbit状态位;如果操作失败则设置badbit状态位。
●我们通常在while循环结构的首部用流读取运算符输入一系列值。当遇到文件结束符时,流读取运算符返回0。
●不带参数的get函数读取(输入)一个字符,并返回该字符;当遇到输人流中的文件结束符时.返回EOF。
●带一个字符型参数的get成员函数输入一个字符。当遇到文件结束符时,函数返回EOF,否则返回对istream对象的引用,并用该引用再次调用get函数。
●带有三个参数的get成员函数,其三个参数分别是接收字符的字符数组、字符数组的大小和分隔符(默认值为'\n')。函数或者在读取比指定的最大字符数少一个字符后结束,或者在遇
到分隔符时结束。空字符终止输入的字符串。函数不把分隔符放到字符数组中,但是分隔符仍然会保留在输入流中。
●成员函数getline与带三个参数的get函数类似。getline要去除输入流中的分隔符,但是不把它存放在字符串中。
●成员函数ignore用于在需要时跳过流中指定数量的字符(默认个数是1),或在遇到指定的分隔符(默认分隔符是EOF)时结束。
●成员函数putback将最后一次用get从输人流中读取的字符放回到输入流中。
●peek成员函数从输入流返回下一个字符,但不从流中删除这个字符。
●C++使用的是类型安全的I/O操作。如果>>或<<运算符接收到了非法的数据类型,那么系统将设置各种错误标志位,用户可根据这些标志位来判断操作I/O的成功与失败。
●调用成员函数read、write可实现无格式输入/输出。这两个函数分别把一定量的字节输入内存和从内存中输出。这些字节都是未经任何格式化的,仅仅是以原始数据形式输入或输出。
●成员函数gcount返回函数read从输入流中读取的字符个数。
●成员函数read把指定个数的字符输入到字符数组中。如果读取的字符个数少于指定的数目,就设置标志位failbit。
●如下方法可改变流中整数的基数:使用流操纵算子hex可设置十六进制基数(基数为16)、使用流操纵算子oct可设置八进制基数(基数为8)、使用流操纵算子dec可恢复十进制基数。只有显式地改变流的基数,否则流的基数是不变的。
●流操纵算子setbase也可以为整数输出设置基数。流操纵算子setbase带有一个整数参数10、8或16。
●流操纵算子setprecision或成员函数percision控制浮点数小数点后面的位数。设置了精度以后,该精度对之后所有的输出操作都有效,直到再一次设置精度为止。无参数的成员函数percision返回当前的精度。
●使用任伺参数化的流操纵算子都必须在程序中包含头文件iomanip.h。
●成员函数width设置当前域宽并返回以前设置的域宽。如果显示数据所需的宽度比设置的域宽小,空位用填充字符填充。域宽设置仅对下一次流读取或流插入操作有效;然后域宽隐式设为0(可以输出任意长度的序列值)。长度大于域宽的值也可以完整输出。不带参数的函数width返回当前域宽。流操纵算子setw也可以用来设置城宽。
●在输入操作中,流操纵算子setw用于设置字符串长度的最大值。如果输入子一个长度大于最大值的字符串,那么该字符串将被分为若干个长度不大于限定值的字符串。
●用户可以建立自己的流操纵算子。
●成员函数setf、unsetf和flags控制标志设置。
●skipws标志指示>>跳过输入流中的空白字符。流操纵算子ws还可用于跳过输入流中的前导空白字符。
●格式标志在类ios中被定义为枚举值。
●虽然成员函数flags、setf和unsetf可以控制格式标志,但是许多程序员更喜欢使用流操纵算子。程序员可以用按位或操作(|)把各种标志选项结合在一个long类型的值中。调用成员函数flags并指定要进行或操作的标志选项就可以在流中设置这些标志,并返回一个包括以前标志选项的long类型的值。返回值通常要保存起来,以便用保存值调用flags来恢复以前的选项。
●flags函数必须指定一个代表所有标志设置的值。而带有一个参数的函数setf指定的标志与现存的标志设置进行或操作,形成新的格式状态。
●设置showpoint标志是为了强制输出浮点数的小数点和由精度指定的有效数字的个数。
●left标志可以使输出域左对齐并把填充字符放在输出数据的右边,riiht标志可以使输出域右对齐并把填充字符放在输出数据的左边。
●internal标志指示将一个数的符号位(设置了ios::showbase标志时为基数)在域宽内左对齐,数值右对齐,中间的空白由填充字符填充。
●left、right和internal标志包含在ios::adjustfield中。
●成员函数fill用于设置与left、right和internal一起使用的使输出域对齐的填充字符;如果没有特别指定,空格即为填充字符。fill函数返回以前设置的填充字符。流操纵算子setfill同样也可设置填充字符。
●静态成员ios::basefield包括oct、hex和dec位,这些位分别指定把整数作为八进制、十六进制和十进制值处理。如果没有设置这些位,则流插入运算默认整数为十进制数,流读取运算按提供的方式处理数据。
●设置showbase标志可强制输出整数值的基数。
●ios::scientific和ios::fixed标志包含在静态数据成员ios::floafield中。这些标志用于控制浮点数的输出格式。设置scientific标志使浮点数按照科学记数法格式输出,设置fixed标志使浮点
数按照precision成员函数指定的精度输出。
●函数调用cout.setf(O,ios::floatfield)恢复浮点数的默认显示格式。
●设置1os::uppercase标志用来使大写的x和E分别同十六进制整数和以科学记效法表示的浮点数一起输出。一旦设置ios::uppercase标志,十六进制数中的所有字母都转换成大写。
●无参数的成员函数flags只返回格式标志的当前设置(long类型的值)。带一个long类型参数的成员函数flags按参数指定的格式设置标志并返回以前的标志设置。
●成员函数setf设置参数所指定的格式标志,井返回前一次的标志设置值(long类型的值)。成员函数setf(long、setbits、long resetBits)清除resetBits中的位,然后设置resetBit位。
●成员函数unsetf清除已设置的标志并返回清除前的标志值。
●参数化的流操纵算子setiosflags与成员函数flags执行同样的功能。
●参数化的流操纵算予resetiosflags与成员函数unsetf执行同样的功能。
●流的状态可以用类ios中的位来检测。
●当遇到文件结束符时,输入流中会被自动设置eofbit。可以在程序中用成员函数eof确定是否设置了eofbit。
●当流中发生格式错误时虽然会设置failbit,但是字符并未丢失。成虽函数fail判断流操作是否失败,这种错误通常可恢复。
●当发生导致数据丢失的流格式错误时,设置badbit。成员函数bad判断流操作是否失败,这种严重错误通常不可修复。
●如果函数bad、fail和eof全都返回false,则成员函数good返回true。应该只对“好”的流进行I/O操作。
●成员函数rdstate返回流的错误状态。
●成员函数clear通常用于把一个流的状态恢复为“好”,从而可以对该流继续执行I/O操作。
●为保证输出在下一个输入前显示,C++提供了成员函数如tie,该函数可以实现输入/输出操作的同步。




术 语
bad member function bad成员函数 end-of-file 文件尾
badbit endl
cerr eof member function eof成员函数
cin eofbit
clear member function clear成员函数 extensibility 可扩展性
clog fail member function fail成员函数
cout failbit
dec stream manipulator dec流操纵算子 field width 域宽
default fill character(space) 默认填充字符(空格) fillcharacter 填充字符
default precision 默认精度 fill member function fill成员函数
flags member function flags成员函数 ostream class ostrearm类
fush member function flush成员函数 padding 填充
nush stream manipulator flush流操纵算子 parameterized stream manipulator 参
format flags 格式标志 数化流操纵算子
fomat states 格式状态 peek member funotion peek成员函数
fomatted I/O 格式化I/O precision member function precision成员函数
fstream class fstream类 predefined streams 预定义的流
gcount member function gcount成员函数 put mereber function put成员函数
get member function get成员函数 putback member function putback成员函数
getline mereber function getline成员函数 rdstate member function rdstate成员函数
good member function good成员函数 read member function read成员函数
hex stream manipulator hex流操纵算子 resetiosflags stream manipulator resetiosflags流
ifstreamclass ifstream类 操纵算子
ignore member function ignore成员函数 righ-justified 右对齐
in-core formatting 内核格式化 setbase stream manipulator setbase流操纵算子
in-memory formatting 内存格式化 setf member function setf成员函数
<iomanip.h> standard header file<iomanip.h>标 setfill steam manipulator setfill流操纵算子
准头文件 setiosflags stream manipulator setiosflags流操
ios class ios类 算子
ios::adjustfield setprecision stream manipulator setprecision流操
ios::basefield 纵算子
ios::fixed setw stream manipulator setw流操纵算子
ios::floatfield skipws
ios::intenal stream class libraries 流类库
ios::scientific stream-extraction operator(>>) 流读取运算符
ios::showbase stream input 流输入
ios::showpoint steam-insertion operator(<<) 流插入运算符
ios::showpos stream manipulator stream流操纵算子
iostream class iostream类 streamoutput 流输出
istream class istream类 tie member function tie成员函数
leadingO(octal) 八进制值的开头 type-safe I/O 类型安全I/O
leading0x or 0X(hexadecimal) 十六进制值的 unformatted I/O 无格式I/O
开头 unsetf member function unsetf成员函数
left左边 uppercase 大写
left-justified 左对齐 user-defined streams 用户自定义流
oct stream manipulator oct流操纵算子 whitespace charecters 空白字符
ofstream class ofsteam类 width 宽度
operator! member function operator!成员函数 write member function write成员函数
operator void* member functlon operator void* ws member function ws成员函数
成员函数




自测练习


11. 1填空
a)重载的流运算符函数经常定义为类的——函数。
b)能够设置的格式对齐位包括——、——和——。
c)C++中的输入/输出是以字节——的形式实现的。
d)参数化的流操纵算子——和——用于设置和清除格式化状态标志。
e)大多数C++程序都要包含——头文件。该文件中包含了所有输入/输出流操作所需的基本信息。
f)成员函数——和——用于设置和清除格式化状态标志。
g)头文件——中包含了执行内存格式化所需的信息。
h)当使用带参数的操纵算子时,程序中必须包含头文件——。
i)头文件——中包含了处理用户控制的文件操作所需的信息。
j)流操纵算子——向输出流中插入一个换行符并刷新输出缓冲区。
k)头文件——中包含了用C、C++语言式I/O混合编程所需的信息。
l)类ostream的成员函数——用于执行无格式输出。
m)类——支持输入操作。
n)标准错误流的输出发送给流对象——或——。
o)类——支持输出操作。
P)流插入运算符是——。
q)与系统中标准设备对应的4个对象是——、——、——和——。
r)流读取运算符是——。
s)流操纵算子——、——和——分别指定整数按八进制、十六进制、十进制格式显示。
t)浮点数的默认精度值是——。
u)设置——标志位可使显示的正数前面带有一个加号。


11.2判断下列说法是否正确。如果不正确,请说明原因。
a)带一个long类型参数的流成员函数flags(按参数值设置flags状态变量,并返回以前设置的标志值。
b)重载流插入运算符<<和流读取运算符>>是为了处理所有的标准数据类型,包括字符串、内存地址(只能用流插入运算符)和所有用户自定义的数据类型。
c)无参数的成员函数flags()可以设置状态变量flags中的所有状态位。
d)流读取运算符的参数是对istream对象的引用和对自定义类型对象的引用,返回对istream对象的引用。
e)流操纵算子ws可跳过输人流中的前导空白字符。
f)流插入运算符<<的两个参数是对istream对象的引用和对自定义类型对象的引用,返回对istream对象的引用。
g)用流读取运算符>>进行输入操作总会跳过输入流中的前导空白字将。
h)输入、输出的特性是由C++本身所提供的。
i)流成员函数rdstate()返回当前流的状态。
j)cout流通常是与显示器相连的。
k)如果成员函数bad()、fail()和eof()都返回false,则流成员函数good()返回true。
l)cin流通常是与显示器相连的。
m)如果在流操作期间发生了不可恢复的致命错误,成员函数bad()返回true。
n)到cerr的输出是非缓冲输出,到clog的输出是缓冲输出。
o)当设置ios::showpoint标志位时,浮点数被强制以默认精度格式(6位小数位)输出(假定未改变精度值使浮点数按指定精度输出)。
P)类ostream的成员函数put用于输出指定数目的字符。
q)流操纵算子dec、oct、hex只对下一个输出整数有效。
r)在输出操作中,内存地址是以long类型表示的。


11.3用一条C++语句实现下述要求。
a)输出字符串”Enter your name:”。
b)设置一个标志,使科学记数法中的指数以及十六进制数中的宇母按大写的格式输出。
c)(S出char*类型变量smng的地址。
d)设置一个标志.以科学记数法显示浮点数。
e)输出int*类型变量integerPtr的地址。
f)设置一个标志,使得在输出整数时,八进制数和十六进制数显示出其基数。
g)输出float*类型变量fioatPtr所指向的值。
h)当所设置的域宽长度大于输出数据所需宽度时,用成员函数设置填充字符'*'。再写一条用流操纵算子实现该功能的语句。
i)用类ostream的函数put在一条语句中输出字符'O',、'K'。
j)从输入流中获取下一个字符,但并不提取它。
k)采用两种不同的方法,用类istream的成员函数get向char类型变量c输入一个字符。
l)输出并删除输入流中的下6个字符。
m)用类istream的成员函数read给char类型数组line输入50个字符。
n)读入10个字符到字符数组name中,当遇到分隔符,'.'时结束读操作,但并不删除输入流中的分隔符。另外再写一条语句完成上述功能,但需要删除输入流中的分隔符。
o)用类istream的成员函数gcount统计字符型数组line中的字符个数(line中的字符是通过调用类istream的成员函数read来输入的),然后根据统计的字符个数,用类ostream的成员函数write输出line中的字符。
p)分别编写两条语句,用成员函数和流操纵算子刷新输出缓冲区。
q)输出下列值:124、18.376、'Z'、1000000和"String"。
r)用成员函数输出当前浮点数的精度。
s)给int类型变量months输入一个整数值,给float类型变量percentageRate输入一个浮点数。
t)用流操纵算子输出1.92、1.925和1.9258,精度是三位小数位。
u)用流操纵算子分别按八进制、十六进制、十进制格式输出整数100。
v)按八进制、十六进制、十进制格式输出整数100,要求用同一个流操纵算子来改变整数的基数。
w)按右对齐方式、以10位域宽输出1234。
x)把字符读入字符数组line中,当遇到指定的分隔符'z'时或读取的字符个数达到限定值20(包括空字符)时,停止读取操作,该语句不从输入流中读取分隔符。
y)按域宽x、精度y(x、y为整型变量)输出double类型值87.4573。


11.4指出并纠正下列语句中的错误。
a) cout << "Value Of x <= y is:" << x <= y;
b)下面的语句要输出字符'c'的整数值:
cout << 'c';
c) cout << ""A string in quotes"";


11.5写出下面语句的输出结果。
a) cout<< "12345" << endl;
cout.width(5);
cout.fill('*');
cout << 123 << endl << 123;
b) cout << setw( 10 ) << setfill( '$' ) << 10000;
c) cout << setw( 8 ) << setprecision( 3 ) << 1024.987694;
d) cout << setiosflags( ios::showbase ) << oct << 99
<< endl << hex << 99;
c) cout << 100000 << endl
<< setiosflags(ios::showpos) << 100000;
f) cout << setw( 10 ) << setprecision( 2 ) <<
<< setiosflags(ios::scientific) << 444.93738;




自测练习答案


11.1
a)友元。b)ios::left、ios::right和ios::internal。c)流。d)setiosflags、e)iostream.h。
f)setf、unsetf g)strstream.h。h)iomanip.h。i)fstleam.h。j)endl。k)stdiostream.h。l)write。
m)ist蹲m)istream。 n)cerr、clog。o)ostream。P)<<。q)cin、cout、cerr和clog。 r)>>。s)ocl、hex、
dec。t)6位精度。u)ios::showpos。
11.2
a)正确。
b)不正确。重载的流插入运算符和流读取运算符不能用于所有的用户自定义类型。程序员必须为每一个用户自定义类型提供重载该运算符的运算符函数。
c)不正确。无参数的成员函数flags()只返回状态变量flags的当前值。
d)正确。
e)正确。
f)不正确。如果要重载流插入运算符,流插入运算符的两个参数必须是对ostream对象的引用和对自定义类型的对象的引用,返回对ostream对象引用。
g)正确。除非ios::skipws未置位。
h)不正确。C++的输入、输出特性是C++标准库的一部分,C++语言本身并不包括输入、输出和文件处理能力。
i)正确。
j)正确。
k)正确。
l)不正确。cin流通常是与计算机的键盘相连。
m)正确。
n)正确。
o)正确。
P)不正确。类ostream的成员函数put用于输出单个的字符。
q)不正确。流操纵算子dec、oct、hex用于设置输出整数的基数,直到下一次设置时或者在程序终止时才会改变。
r)不正确。在输出操作中,内存地址的默认显示方式是十六进制格式。如果要按long类型显示,则必须先转换成对应于long类型的值。


11.3
a) cout << "Enter your name:";
b) cout.setf(ios::uppercase);
c) cout << (void*)string
d) cout.setf(ios::scientific,ios::floatfield);
e) cout << integerPtr;
f) cout << setiosflags(ios::showbase);
g) cout << *floatPtr;
h) cout.fill('*');
cout<< setfill('*' );
i) cout.put('O').put('K');
j) cin.peek();
k) c = cin.get();
cin.get(c);
l) cin.ignore(6);
m) cin.read(line,50);
n) cin.get(name,1O,'.');
cin.getline(name,lO,'.');
O) cout.write(line, cin.gcount());
p) cout.flush();
cout << flush;
q) cout << 124 << 18.376 << 'z' << 1000000 <<"string";
r) cout << cout.precision();
s) cin >> months >> percentageRate;
t) cout << setprecision( 3 ) << 1.92 << '\t'
<< 1.925 << '\t' << 1.9258;
u) cout << oct << 100 << hex << 100 << dec << 100;
v) cout << 100 << setbase( 8 ) << 100 << setbase( 16 ) << 100;
w) cout << setw( 10 ) << 1234;
x) cin.get(line,20,'z');
y) cout << setw( x ) << setprecision( y ) << 87.4573;


11.4
a)不正确:运算符<<的优先级比<=高,语句求值不正确,因此编译器会报告错误。
纠正:在表达式x<=y两边加上括号。
b)不正确:不能像在c语言中那样在C++中直接输出字符的ASCII码值。
纠正:如果需要输出某一字符的ASCII值,必须先计算出它的ASCII值再输出,例如:
cout << int('C');
c)不正确:除非使用转义序列来加以区别,否则无法在字符串中输出双引号" "。
纠正:可用下面两种方法之一输出双引号" ":
cout << ' " ' << "A string in quotes" << ' " ';
cout << "\"A string in quotes\"";
11.5
a)12345
** 123
123
b)$$$$$10000
c)1024.988
d)0143
0x63
e)100000
+100000
f) 4.45e+02




练 习
11.6 用一条C++语句实现下述要求:
a)以左对齐方式输出整数40000,域宽为15。
b)把一个字符串读到字符型数组变量state中。
c)打印有符号数200和无符号数200。
d)将十进制整数100以0x开头的十六进制格式输出。
e)把字符读到数组s中,直到遇到字符'p'或读取的字符个数达到限定值10时终止读取操作。同时从输入流中读取分隔符并删除。
f)用前导O格式打印1.234,域宽为9。
g)从标准输入流中读取字符串"charecters",将其存储在字符数组s中。读取过程中去掉双引号,读取字符个数的最大限定值为50(包括空字符)。


11.7 编写一个程序,测试十进制、八进制、十六进制格式整数值的输入,分别按三种不同的基数输出。测试数据为10、O10、Ox10。


11.8 编写一个程序,用强制类型转换运算符把指针值转换成各种整数数据类型后,打印出指针值。哪种数据类型打印出奇怪的值?哪种数据类型产生了错误?


11.9 编写一个程序.分别用不同的域宽打印出整数12345和浮点数1.2345。当域宽小于数值的实际需要的域宽时会发生什么情况?


11.10编写一个程序,将100.453627取整到最近似的个位、十分位、百分位,千分位和万分位,打印出结果。


11. 11编写一个程序,从键盘输入一个字符串,判断字符串的长度,然后以字符串长度的两倍作为域宽打印出该字符串。


11. 12编写一个程序,将华氏温度0度~212度转换为浮点型撮氏温度,浮点数精度为3。转换公式如下:
celsius=5.0/9.O * (fahrenheit - 32);
输出用两个右对齐列,摄氏温度前面加上正负号。


11.13在不同的编程语言中,字符串有的是用单引号' '括起,有的是用双引号" "括起。编写一个程序,读取三个不同的字符串suzy、”suzy”和'suzy'。看看单引号和双引号是被忽略了,还是被当作字符串的一部分一起读取了。


11.14图8. 3的程序为类PhoneNumber的输入和输出对象而重载了流读取运算符和流插入运算符。重新编写流读取运算符,使它能够检测下面的输入错误。注意,函数operator>>的代码全部需要重写。
a)输入一个完整的电话号码到一个字符数组中,检测输入的字符总数,例如电话号码(800)555-1212的字符总数为14个。如果输入错误,用流成员函数clear设置ios::failbit位。
b)电话号码中的区号和局号不能以0或1打头。检测区号和局号的第一位,判断是否为 0或1,若是,则用流成员函数clear设置ios::failbit位。
c)区号的中间一位是0或1,检测中间位,判断是否为0或1,如果输入错误,则用流成员函数clear设置ios::failbit位。如果输入正确,即ios::failbit位为0,则把电话号码的三个部分分别复制到对象PhoneNumber的成员areacode、exchange和line中。在主程序里,如果置位ios::failbit,则程序打印出一条出错消息.并且不打印电话号码而结束运行。


11.15 编写完成下列要求的程序:
a)建立用户自定义类Point,该类包含private整数数据成员xCoordinate和yCoordinate,并在类中声明了重载的流插入和流读取运算符函数为其友元。
b)定义流插入和流读取运算符函数。流读取运算符函数判断输入的数据是否合法,如果是非法数据,则置位ios::failbit以指示输入不正确。发生错误后,流插入运算符函数不显示Point的对象(点)的坐标信息。
c)编写函数main,用重载的流插入运算符和流读取运算符测试自定义类Point的输入和输出。


11. 16编写完成下列要求的程序:
a)建立用户自定义复数类Complex,类中包括private整数数据成员real和imaginary,并声明了重载的流插入和流读取运算符函数为其友元。
b)定义流插入和流读取运算符函数。流读取运算符函数判断输入的数据是否合法,如果是非法数据,则置位ios::failbit以指示输入不正确。必须按以下格式输入:
3 + 8i
c)数据可为整数或负数,还可以只给其中一个数赋值。未给出的数值,由相应的数据成员设置为0。当发生输入错误时,流插入运算符不显示该复数值。输出格式与上述的输入格式相同,对于为负的虚部要打印出负号。
d)编写函数main,用重载的流插入运算符和流读取运算符测试自定义类Complex的输入和输出。


11.17用for结构为ASCII字符集中ASCII码值从33—126的字符打印出一张ASCII码表。要求输出十进制值、八进制值、十六进制值和ASCII码值,并在程序中使用流操纵算子dec、oct和hex。


11. 18编写一个程序,用成员函数getline和带三个参数的成员函数get输入带有空字符的字符串。get函数不读取分隔符,分隔符仍保留在输入流中,并让getline从输入流中读取并删除分隔符。把未读取的字符留在输入流中会发生什么情况?


11. 19编写一个程序,建立用户自定义流操纵算子skipwhite以跳过输入流中的前导空白字符。
该流操纵算子使用ctype.h函数库中的isspaee函数测试输入的字符是否是空白字符。要求用istream的成员函数get来读取每一个字符,当遇到一个非空白字符时,流操纵算子skipwhite把该字符放回到输人流中,返回对istream对象的引用。
建立一个main函数,测试自定义流操纵算子(在main函数中清除ios::skipws标志位,以保证流读取运算符无法自动跳过空白字符)。然后输入一个以空白字符开头的字符,对流操纵算子进行测试,读取完毕之后,输出所读取的字符以证实空白字符确实未被输入

你可能感兴趣的:(C++)