C++格式化输入输出

C++共有15个 输入输出 格式标记位,这15个标记位均为bit位,每个标记位都有自己的含义,且可以单独设置。

格式标记位的取值为0或1:0表示关闭(不使用此格式),1表示开启(使用此格式)。

15个标记位的含义可参考下面三张表:

标记位
含义
boolalpha    如开启,则输入和输出使用bool值(即Ture或False)
showbase     如开启,则对于输出,使用C++ 基数前缀(0,0x)
showpoint    如开启,则显示末尾的小数点
uppercase    如开启,则对于16进制,使用大写字母;对于10进制,使用E表示法
showpos      如开启,则在正数前面加上+

标记位
含义
dec        如开启,则使用基数10(进行输出)
oct        如开启,则使用基数8
hex        如开启,则使用基数16
fixed      如开启,则使用定点计数法
scientific 如开启,则使用科学计数法
left       如开启,则使用左对齐
right      如开启,则使用右对齐
internal   如开启,则符号或基数前缀左对齐,值右对齐

标记位
含义
skipws     如开启,则跳过输入流中的空白字符
unitbuf    如开启,则每次输出操作后都会清空缓冲区




先来看一个简单的程序:

#include <iostream>
using namespace std;

int main()
{
int x;
x = cout.setf(ios::showpos);
cout << x << endl;

x = cout.setf(ios::uppercase);
cout << x << endl;

system("pause");
return 0;
}
输出结果是:

setf()函数用于设置格式标记,函数接受一个设格式常量作为参数,在设置成功之后函数会返回一个值,该值指出了所有15个标记的上一次设置情况。

但将这个返回值进行输出,并不是每一个标记位的bit值,而是一个整数,为什么?

实际上,这15个bit值视为一个整体,从而组成一个二进制数,并能够转化为十进制数。

这15个标记位的排列顺序是:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha

比如,setf()函数第一次的返回值是4098,这个值实际上是输出格式的初始状态,转化二进制为001000000000010,那么格式状态为:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha
0 0 1 0 0 0 0 0 0 0 0 0 0 1 0

而6146转化为二进制001100000000010,这一次的值反映的是开启了showpos位后的格式状态:
uppercase unitbuf skipws showpos showpoint showbase scientific right oct left internal hex fixed dec boolalpha
0 0 1 1 0 0 0 0 0 0 0 0 0 1 0

两次对比,我们可以看出,的确是在初始状态的基础上开启了showpos位。

接着我们来看看格式常量,格式常量一共有18个,其中15个用于打开相应的格式标记为,另外3个做为指示功能用

#include <iostream>

using namespace std;

int main()
{
cout << "boolalpha " << ios::boolalpha <<endl;
cout << "dec " << ios::dec << endl;
cout << "fixed " << ios::fixed << endl;
cout << "hex " <<ios::hex << endl;
cout << "internal " << ios::internal << endl;
cout << "left " << ios::left << endl;
cout << "oct " << ios::oct << endl;
cout << "right " << ios::right << endl;
cout << "scientific " << ios::scientific << endl;
cout << "showbase " << ios::showbase <<endl;
cout << "showpoint " << ios::showpoint <<endl;
cout << "showpos " << ios::showpos <<endl;
cout << "skipws " << ios::skipws << endl;
cout << "unitbuf " << ios::unitbuf << endl;
cout << "uppercase " << ios::uppercase <<endl;

cout << endl;
cout << "basefield " << ios::basefield << endl;
cout << "adjustfield " << ios::adjustfield << endl;
cout << "floatfield " << ios::floatfield << endl;

system("pause");
return 0;
}

格式常量
十进制值
意义
ios::boolalpha
1 开启boolalpha标记位,输入和输出使用bool值(即Ture或False)
ios::showbase
512 开启showbase标记位,对于输出,使用C++ 基数前缀(0,0x)
ios::showpoint
1024 开启showpoint标记位,显示末尾的小数点
ios::uppercase
16384 开启uppercase标记位,对于16进制,使用大写字母;对于10进制,使用E表示法
ios::showpos
2048 开启showpos标记位,在正数前面加上+

格式常量
十进制值
意义
格式常量
十进制值
意义
ios::basefield
74 指示相关标记位:dec、oct、hex ios::dec
2 开启dec标记位,使用基数10
ios::oct
64 开启oct标记位,使用基数8
ios::hex
8 开启hex标记位,使用基数16
ios::floatfield
260 指示相关标记位:fixed、scientific ios::fixed
4 开启fixed标记位,使用定点计数法
ios::scientific
256 开启scientific标记位,使用科学计数法
ios::adjustfield
176 指示相关标记位:left、right、internal ios::left
32 开启left标记位,使用左对齐
ios::right
128 开启right标记位,使用右对齐
ios::internal
16 开启internal标记位,符号或基数前缀左对齐,值右对齐



注意:这些都是常量,是作为 函数参数 来设置格式状态,而不是格式标记位的存储空间。

15个蓝色的格式常量用来打开对应的格式标记位,如果将其十进制值转化为二进制,再于标记位顺序表比对,就可以看出来。

3个绿色的格式常量用来指示标记位,为什么要指示?比如:dec、oct、hex是不可能同时打开的,而ios::basefield则指示这三个标记位为一组,74=2+64+8,这意味着它转化为二进制的比对情况是dec、oct、hex为1,但它不是设置标记位,而是指示,具体原理在setf()函数中详细解释。

最后来看看setf()函数:

setf()函数有两种原型,一种是fmtflags setf ( fmtflags );

它接收一个参数,该参数是一种 标记类型,提供实参时,可以是整数,该整数转化为二进制后赋给格式状态。但这种方法抽象且不安全。

也可以将格式常量作为实参提供给函数,在这种情况下,setf()函数会打开相应的标记位,且不会影响其它标记位。但这种方法仍不安全。很明显,既打开dec标记位,又打开oct标记位是没有意义的。

另一种原型是fmtflags setf ( fmtflags , fmtflags );

它接收两个 标记类型 的参数。第一个参数指出要打开的标记位,第二个参数则是指示要清除的一批相关位。

比如:cout.setf( ios::hex, ios::basefield ); 这表示使用16进制输出格式。首先,ios::basefield指示出了要清除的标记位,setf()函数将ios::basefield所指示的标记位,即dec、oct、hex全部清零。然后ios::hex使得setf()函数打开hex标记位。这是一种安全的方法,避免了同时打开dec、hex两个标记位等没有实际意义的情况发生。

setf()是如何实现清除的?

ios::basefield转化为二进制000000001001010,这三个1的位置指示的是dec、oct、hex标记位。setf()函数将这个二进制数取反111111110110101,然后与原格式状态标记位进行“与”操作,使得原格式状态的dec、oct、hex标记位为0,而其它标记位不变。(参看《C++ primer plus》683页位操作)

然后setf()函数根据第一个参数ios::hex将格式状态的hex标记位打开,其它标记位不变。至此,格式设置就成功完成了。我们也可以看出,setf()函数不会影响无关标记位的状态。

转载地址:http://blog.csdn.net/angelcm51/article/details/2330496
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章