14.4.6 使用setf函数和unsetf函数设定格式关键字
flags函数已能够很好地设定格式状态字,但在设定前都要读取当前格式状态字,变化后采用位复制的形式进行修改,对每个位都进行了操作,这似乎有些麻烦,为此,ios_base类中提供了成员函数setf和unsetf来对格式状态字进行设置,与flags函数的本质区别在于setf函数和unsetf函数只对参数中指定的位进行操作,对其他位没有影响,如下所述。
(1)一元setf函数,对应的原形如下所示。
long setf(long ff);这种调用方式返回当前格式状态字,并根据ff将格式状态字的相应位设置为1,使其有效,但不影响所有其他的标志位,一元setf函数实际上等价于如下代码。 long flags(flags()|ff);
通俗地说,一元setf函数将格式状态字中与ff中为1的位相对应的位设定为1。
(2)二元setf函数,对应的原形如下所示。
long setf(long ffadd,long ffremove);这种调用方式同样返回当前格式状态字,但与一元setf函数不同之处在于其多了一个参数ffremove,实际上,二元setf函数等价于如下代码。 long flags(flags()&~ffremove); long flags(flags()|ffadd);通俗地说,二元函数首先将格式状态字中与第2个参数中为1的位相对应的位设置为0,而后将与第1个参数中为1的位相对应的位设置为1,而其他位不发生变化。这种调用形式如前面所提的dec、hex和oct等意义并列的标志位,以要修改的基数为例,只要将ios_basefield作为第2个参数即可,如下所示。 cout.setf(ios_base:hex,ios_base:basefield);
类似的并列意义标志位如表14.6所示。
(3)unsetf函数。
unsetf函数只有一种函数调用形式,如下所示。
long unsetf(long ffremove);
同setf函数意义相反,unsetf根据ffremove将格式控制字的对应位设置为0,使其失效,如示例代码14.10所示。
代码14.10 格式控制字与setf的用法SetfSample
<———————————文件名:example1410.cpp————————————————> 01 #include<iostream> 02 using namespace std; 03 int main() 04 { 05 int x=255; 06 cout<<x<<endl;//默认按十进制输出 07 cout. setf(ios_base:hex,ios_base:basefield); 08 cout<<x<<endl;//按十六进制输出 09 cout. setf(ios_base:showbase|ios_base:uppercase);//设置基指示符输出和 10 //数值中的字母大写输出 11 cout<<x<<endl; 12 cout. setf(ios_base:dec,ios_base:basefield);//恢复到十进制输出 13 cout. setf(ios_base:showpos);//正数前加+号 14 cout<<x<<endl; 15 bool y=true; 16 cout<<y<<endl;//bool型默认输出0或1 17 cout. setf(ios:boolalpha); 18 cout<<y<<endl;//输出true或false 19 return 0; 20 }
输出结果如下所示。
255 ff 0XFF +255 1 true
【代码解析】代码演示了如何使用setf函数和unsetf函数设置格式状态字,默认情况下,系统按十进制形式输入输出,所以第1个对x的输出操作,结果为255,而后通过代码第7行的二元setf函数设置16为输入输出的基,所以第2个对x的输出操作结果为ff,通过代码第9行的语句“cout.setf(ios_base:showbase|ios_base:uppercase);”中showbase有效设置了输出基指示符(八进制为0,十六进制为0x),uppercase有效地将十六进制采用大写的A-F以及0X,所以第3个对x的输出结果为0XFF,第13行语句“cout.setf(ios_base:showpos);”命令用于在正数前输出正号,需要注意的是输出正号只是针对十进制形式的,对八进制和十六进制而言,系统统一当成无符号数来处理,所以在第5个对x的输出之前,先将输入输出的基改回十进制,结果是+255,对bool型变量y来说,系统默认以0和1分别代表false和true输出,但只要设定了常量boolalpha有效,便可以输出“true”或“false”的形式。
说明
在输入输出基的选择上,编译器一般采取如下规则,只有当oct、dec和hex对应的位分别为1,0,0时,便采用八进制,分别为0,0,1时,便采用十六进制,其他情况下均采用默认的十进制形式。