ITEEDU

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标志,从而控制了浮点数的尾数零和小数点的输出。

  // Fig. 11.21: fig11_21.cpp
 // Controlling the printing of trailing zeros and decimal
 // points for floating-point values.
 #include <iostream.h>
#include <iomanip.h>
#include <math.h> int main() { cout << "Before setting the ios::showpoint flag\n" << "9.9900 prints as: "<< 9.9900 << "\n9.9000 prints as: "<< 9.9000 << "\n9.0000 prints as: "<< 9.0000 << "\n\nAfter setting the ios::showpoint flag\n"; cout.setf( ios::showpoint ); cout << "9.9900 prints as: "<< 9.9900 << "\n9.90O0 prints as: "<< 9.9000 << "\n9.0000 prints as: "<< 9.0000 << endl; return 0; }

输出结果:

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控制整数值在域宽内左对齐和右对齐。

 // Fig. 11.22: fig11_22.cpp
 // Left-justification and right-justification.
 #include <iostream.h>
 #include <iomanip.h>
 int main()
{
   int x = 12345;
   cout << "Default is right justified:\n"
       << setw(10) << x << "\n\nUSING MEMBER FUNCTIONS"
       << "\nUse serf to set ios::left:\n" << setw(10);
   cout.setf( ios::left, ios::adjustfield );
   cout << x << "\nUse unsetf to restore default:\n";
   cout.unsetf( ios::left );
   cout << setw( 10 ) << x
       << "\n\nUSING PARAMETERIZED STREAM MANIPUAATORS"
       << "\nUse setiosflags to set ios::left:\n"
       << setw( 10 ) << setiosflags( ios::left ) << x
       << "\nUse resetiosflags to restore default:\n"
       << setw( 10 ) << resetiosflags( ios::left )
       << x << endl;
   return 0;
 }

输出结果:

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标志强制打印了加号。

  // Fig. 11.23: figll_23.cpp
 // Printing an integer with internal spacing and
 // forcing the plus sign.
 #include <iostream.h>
 #include <iomanip.h>
 int main()
 {
   cout << setiosflags( ios::internal | ios::showpos )
      << setw( 10 ) << 123 << endl;
    return  O;
  }

输出结果:

+ 123

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

11.7.4 设置填充字符(fill、setfill)

成员函数fill设置用于使输出域对齐的填充字符,如果不特别指定,空格即为填充字符。fill函数返回以前设置的填充字符。图11.24中的程序演示了使用成员函数fill和流操纵算子,setfill来控制填充字符的设置和清除。

// Fig. 11.24: fig11_24.cpp
// Using the fill member function and the setfill
// manipulator to change the padding character for
// fields larger than the values being printed.
#include <iostream.h>
finclude <iomanip.h>
int main()
{
int x = 10000;
cout << x << "printed as iht right and left justified\n"
<< "and as hex with internal justification.\n"
<< "Using the default pad character (space):\n";
cout.setf( ios::showbase );
cout << setw( 10 ) << x << '\n';
cout.setf( ios::left, ios::adjustfield );
cout << setw( 10 } << x << '\n';
cout.serf( ios::internal, ios::adjustfield );
cout << setw( 10 ) << hex << x;
cout << "\n\nUsing various padding characters:\n";
cout.setf( ios::right, ios::adjustfield );
cout.fill( '*' );
cout << setw( 10 ) << dec << x << '\n';
cout.setf( ios::left, ios::adjustfield );
cout << setw( 10 ) << setfill( '%' ) << x << '\n';
cout.setf( ios::internal, ios::adjustfield );
cout << setw( 10 ) << setfill( '^' ) << hex << x << endl;
return 0;
}

输出结果:

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标志强制整数按十进制、八进制和十六进制格式打印。

// Fig. 11.25: figll_25.cpp
// Using the ios::showbase flag
#include <iostream.h>
#include <iomanip.h>
int main()
{
int x = 100;
cout << setiosflags( ios::showbase )
<< "Printing integers preceded by their base:\n"
<< x << '\n'
<< oct << x << '\n'
<< hex << x << endl;
return 0;
}

输入结果:

Printing integers preceded by their base:

I00

0144

0x64

图 11.25 使用ios::showbase标志s

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中的程序示范了以定点格式和科学记数法显示的浮点数。

  // Fig. 11.26: flg11_26.cpp
 // Displaying floating-point values in system default,
 // scientific, and fixed formats.
 #include <iostream.h>
 int main()
 {
   double x = .001239567, y = 1.946e9;
   cout << "Displayed in default format:\n"
       << x << '\t' << y << '\n';
   cout.setf( ios::scientific, ios::floatfield );
   cout << "Displayed in scientific format:\n"
       << x << '\t' << y << '\n';
   cout.unsetf( ios::scientific );
   cout << "Displayed in default format after unsetf:\n"
       << x << ,\t' << y << ,\n,;
   cout.setf( ios::fixed, ios::floatfield );
   cout << "Displayed in fixed format:\n"
       << x << '\t' << y << endl;
   return 0;
 }

输出结果:

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标志,十六进制数中的所有字母都转换成大写。

// Fig. 11.27: fig11_27.cpp
 // Using the ios::uppercase flag
 #include < iostream.h>
 #include < iomanip.h>
 int main()
 {
     cout << setiosflags( ios::uppercase )
          << "Printing uppercase letters in scientific\n"
         << "notation exponents and hexadecimal values:\n"
         << 4.345e10 << '\n' << hex << 123456789 << endl;
   return O;
 }

输出结果:

Printing uppercase letters in scientific

notation exponents and hexadecimal values:

4.395E+010

75BCD16

图 11.27 使用ios::uppercase标志