14.4.3 格式状态字

    在ios_base类中定义了用于控制输入/输出的格式状态字,以满足不同的I/O需求。由图14.3可知,ostream类是从ios类派生而来的,而ios类是从ios_base类派生而来,在ios_base类中定义了流的格式信息,以及设置和读取这些信息的方法。

    格式状态字是一个32位的long型整数,其每一位都代表了特定的含义。理解格式化常量能更好地理解格式状态字,在ios_base类中,维护了下述枚举结构。


    enum_Fmtflags { skipws=0x0001,//in,跳过输入中的空白 unitbuf=0x0002,//out,插入操作后<<立即刷新缓冲区 uppercase=0x0004,//out,十六进制中的A-F以及X大写 showbase=0x0008,//out,输出时使用前缀,八进制为0,十六进制为0x showpoint=0x0010,//out,强迫显示浮点数末尾的小数点和0 showpos=0x0020,//out,正数前加+号 left=0x0040,//out,输出数据在输出域中左对齐 right=0x0080,//out,输出数据在输出域中右对齐 internal=0x0100,//out,两端对齐,在符号位或基前缀(0或0x)后填充字符 dec=0x0200,//input&output,转换为十进制 oct=0x0400,//input&output,转换为八进制 hex=0x0800,//input&output,转换为十六进制 scientific=0x1000,//out,用科学记数法显示浮点数 fixed=0x2000,//out,使用定点形式显示浮点数 boolalpha=0x4000,//out,输入和输出bool值时,显示true或false adjustfield=0x01c0,//0000 0001 1100 0000 basefield=0x0e00,//0000 1110 0000 0000 floatfield=0x3000,//0011 0000 0000 0000 _Fmtmask=0x7fff,//0111 1111 1111 1111 _Fmtzero=0//0000 0000 0000 0000 };

    上述枚举常量便是格式化常量,每个格式化常量都是一个32位的整型数,而且前15项(从skipws到boolalpha)按enum中的定义顺序分别对应着32位(bit)格式状态字的不同位,前15个格式化常量可以看成是“格式状态字只有某位为1时的取值”。

    格式状态字和格式化常量的关系如图14.4所示,从skipws到boolalpha分别对应着格式状态字的某位,该位为1,允许该格式,否则,禁止该格式。换言之,格式状态字是32个状态位的组合。

    可以通过位与、位或或位反操作来实现不同格式化常量的组合,如下所示。

    14.4.3 格式状态字 - 图1

    图 14.4 格式控制字位对应形象图


    skipws|unibuf;0x0003,即0000 0000 0000 0011,后两位都有效 _Fmtmask=0x7fff,//0111 1111 1111 1111

    _Fmtflags结构中定义的上述结构便可以看成是前15个枚举量位或的结果,同理,adjustfield可以看做“left|right|internal”,basefield可以看成“oct|base|hex”,floatfield可以看成“fixed|scientific”,关于这些格式化常量的具体应用稍后会有详细的介绍。

    诸如left及fixed等格式化常量是在ios_base类里定义的,外部访问时必须用作用域分辨符来存取其值,即直接使用left和fixed是不行的,必须指定为ios_base:left和ios_base:fixed。

    说明

    从_Fmtflags结构的定义可以看出,大部分的格式化常量都是针对输出操作的,针对输入操作的仅有skipws、dec、oct和hex 4个。因此,对格式化状态字的介绍也主要是围绕输出而来的。

    旧的C++标准中是没有ios_base类的,上述格式化常量和后面要介绍的一些设置函数是定义在ios类的,新的C++标准将流类库模板化,ios类也是对basic_ios进行实例化后生成的模板类,因此,诸如格式化常量和设置函数等一些独立类型的信息被转移到一个非模板新类ios_base中,以方便对输入输出流进行控制。本节中所有的示例基于新的C++标准,读者如果使用旧的标准(比如使用诸如“#include<iostream.h>”之类的头文件),则可能需要把诸如“ios_base:left”的格式化常量访问形式改写成“ios:left”。

    说明

    ios类是从ios_base类派生而来的,实际上,本书中所有对格式状态字的访问完全可以用“ios:”的形式,甚至还可以是“ostream:”或“istream:”的形式。