学科分类
目录
C++基础

格式标志

ios类是所有ios类层次的基类,它提供了所有派生类中都需要的流的状态设置、状态报告成员函数,以及精度、域宽设置等成员函数。接下来分别进行学习。

1、格式化状态

在编程中,常常用一个字节(byte)或几个字节来标志某些属性,每个位标志着一个属性,例如,一个字节有8位:00000000,那么我们可以用第一位(右起)表示是否吃饭,1表示吃饭,0表示未吃饭;用第二位表示是否梳洗,1表示梳洗,0表示未梳洗;第三位表示是否上学,1表示上学,0表示未上学,其他各位也可定义相应的含义。如设置状态为00000101,该值就表示,吃了饭,没有洗漱,去上学。这样来标志属性很节省空间,表示起来简单又方便。

在C++中,I/O的输入输出状态就是通过每一个二进制位来设置的,ios基类为流定义了一组状态标志,如下所示:

class ios_base
{
public:
    //……
    typedef implementation_defined1 fmtflags;
    static const fmtflags
        skipws,       //输出时跳过空白
        left,         //输出左对齐
        right,        //输出右对齐
        internal,     //在符号和值之间填充
        boolalpha,    //用符号形式表示真假
        dec,           //以十进制输出
        hex,           //以十六进制输出
        oct,           //以八进制输出
        scientific,   //用科学计数法输出浮点数
        fixed,         //用定点数方式输出实数
        showbase,     //输出前缀,八进制加0,十六进制加0x
        showpoint,    //输出浮点数时总是带小数点
        showpos,      //输出正整数时加"+"
        uppercase,    //输出十六进制时所有字母均用大写
        adjustfield, //与域调整有关的标志组
        basefield,    //与整数基数有关的标志组
        floatfield,   //与浮点数输出有关的标志组
        unitbuf;      //每次输出操作之后刷新
    //……
};

如果设置了某个状态标志位,则对应位为1,否则为0。例如,如果设置了skipws,则相应的二进制位值就为1。

2、格式化操控符

ios类还提供了数个成员函数,用于定义各种I/O格式,实现访问格式标志的功能,这些函数

包括setf()、unsetf()、flags()、flags(flags),它们可以处理所有的格式定义,接下来我们分别来学习这几个函数。

(1)setf()函数

setf()函数用于设置状态标志,把指定位的状态标志设置为1,其函数声明有两种形式,如下所示:

fmtflags ios::setf(fmtflags flag); //第一种形式
fmtflags ios::setf(fmtflags flag, fmtflags mask); //第二种形式

● 第一种形式是用flag设置流的格式,但不会减少之前的流标志,也就是说相当于在原来的流标志的基础上添加flag标志。

● 第二种形式是用flag和mask两个参数共同设定流格式标记,清除mask标志位中不属于flag中的标志。

例如,若要输出数据为十六进制数,则可在输出语句前加如下语句:

cout.setf(ios::hex, ios::basefield);

该语句将状态标志的hex对应位设置为1。当一次要设置多个状态位时,用位“或”符号(|)连接要设置的状态标志位,代码示例如下所示:

cout.setf(ios::scientific | ios::uppercase);
cout << 2006.5 << endl;

在输出时设置状态标志是以科学计数法输出浮点数,并且输出时所有字母均用大写字母。

(2)unsetf()函数

unsetf()函数用于清除状态标志,其函数声明如下所示:

void ios::unsetf(fmtflags mask);

该成员函数的功能是把指定位的状态标志设置为0。例如,在输出数据时设置了showpos位,如果要取消显示“+”符号的状态标志,则可调用unsetf()函数来取消设置,代码如下所示:

cout.unsetf(ios::showpos);

(3)flags()函数

flags()函数用于获取流状态标志位,其函数声明有两种形式,如下所示:

fmtflags ios::flags() const;
fmtflags ios::flags(fmtflags flag);

● 第一种形式调用是返回当前流状态标志。

● 第二种形式调用,返回设置前的状态标志位,然后将这些状态位清除,再以参数作为新格式标志状态。

函数flags()非常有用,它可用于存储当前标志状态,并在适当时机恢复。

学习完上面几个函数,接下来我们通过一个案例来演示其用法,具体代码如例1所示:

例1

 1    #include <iostream>
 2    using namespace std;
 3    int main()
 4    {
 5        float f = 20.2; //定义一个float类型变量
 6        
 7        //设置以科学计数法输出,所用字母均是大写
 8        cout.setf(ios::scientific | ios::uppercase); 
 9        cout <<"f = "<< f << endl;  
 10       
 11        //用flags()函数获取当前流状态标志
 12        cout <<"第一次获取流状态标志:"<< cout.flags() << endl; 
 13        cout.flags(ios::showpos);    //将先前的状态标志都清除,设置showpos标志,
 14        
 15        //再次调用flags()获取当前流状态标志
 16        cout << "第二次获取流状态标志:"<<cout.flags() << endl; 
 17        cout << "设置showpos后,f = "<<f << endl;
 18        cout.unsetf(ios::showpos); //取消showpos标志设置
 19        cout <<"unsetf后, f = "<< f << endl;
 20        system("pause");
 21        return 0;
 22    }

运行结果如图1所示。

图1 例1的运行结果

在例1中定义了一个变量f,然后设置流状态标志scientific和uppercase,以科学计数法输出,并且所用字母都为大写,由图1可以看出,输出的f的格式发生了改变。然后代码12行调用flags()函数获取当前流的状态标志为4613,它对应的二进制数,表示着流的状态设置。代码第13行又调用flags()函数设置showpos位,它会把先前的标志(如scientific等)清除,再设置showpos位,设置后输出当前流状态为+32,流状态发生了改变,而输出f的值也变为+20.2。最后第18行代码调用unsetf()取消showpos位的设置,则输出f的值恢复到原来形式20.2。

多学一招:流状态复制函数

copyfmt()函数

copyfmt()函数实现从流中复制所有的格式定义,其函数声明如下所示:

ios_base& copyfmt(const basic_ios& f);

copyfmt()并不复制流的缓冲区和缓冲区的状态,但是它复制状态中其余的东西,包括所要求的异常和用户给状态添加的所有东西。

点击此处
隐藏目录