Chinaunix首页 | 论坛 | 博客
  • 博客访问: 42451
  • 博文数量: 10
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 9
  • 用 户 组: 普通用户
  • 注册时间: 2015-12-20 12:35
文章分类
文章存档

2016年(5)

2015年(5)

我的朋友

分类: C/C++

2016-08-15 22:22:34

原文地址: C++格式化输入输出 作者:welkin

++共有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
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
using namespace std;

 

int main()
{
    cout << "boolalpha    " << ios::boolalpha <    cout << "dec          " << ios::dec << endl;
    cout << "fixed        " << ios::fixed << endl;
    cout << "hex          " <    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 <    cout << "showpoint    " << ios::showpoint <    cout << "showpos      " << ios::showpos <    cout << "skipws       " << ios::skipws << endl;
    cout << "unitbuf      " << ios::unitbuf << endl;
    cout << "uppercase    " << ios::uppercase <   
    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/archive/2008/04/26/2330496.aspx

 

阅读(792) | 评论(0) | 转发(0) |
0

上一篇:函数后面加一个const的作用(转)

下一篇:没有了

给主人留下些什么吧!~~