C++:IO标志位

(部分摘自《标准C++输入输出流与本地化》)

1. 状态标志.

    1). 每个流对象都维护一个状态变量标记流状态(成功或失败),该变量类型是iostate(实际上是ios_base定义的位域类型),状态变量的不同二进制位用来标记不同状态,共有三个状态标志:

状态标志

作用

所占bit

failbit

出现可挽回的非致命错误

1

badbit

出现不可挽回的致命错误

2

eofbit

到达文件尾

3

goodbit

没有错误

不占bit

    2). 函数

函数

作用

bool fail()

若failbit位被置为1,返回true

bool bad() 

若badbit位被置为1,返回true  

bool eof()

若eofbit位被置为1,返回true

bool good()

若failbit,badbit,eofbit位全为0,返回true

iostate rdstate() const

获取当前流状态变量

void clear (iostate state = goodbit)

重设流状态为state,并覆盖原有状态,默认为ios:goodbit

void setstate (iostate state)

在原有状态基础上添加state状态,其实是clear(rdstate()|state)

 

2. 格式标志.

    1). 除状态变量外,每一个流对象还维护一个fmtflags类型(与iostate类似)的格式变量,用来标记输入输出格式,格式标志有:

位组

格式标志

作用

默认值

所占bit

 

skipws

使用输入操作符时跳过空白字符

设置

1

 

unitbuf

每次操作后刷新缓冲区

Cerr设置,其他对象不设置

2

 

uppercase

字母采用大写

不设置

3

 

showbase

输出整数时加上进制前缀

未设置

4

 

showpoint

按精度输出浮点数(不够补0)

未设置

5

 

showpos

输出非负数时加‘+’

未设置

6

 

adjustfield

left

加入指定字符使输出左对齐

 

right

7

right

加入指定字符使输出右对齐

8

Internal

在符号和数值中间插入指定字符

9

 

basefield

dec

10进制输入/输出

 

dec

10

oct

8进制输入/输出

11

hex

16进制输入/输出

12

floatfield

scientific

浮点数按科学计数法输出

无,由浮点数量级决定

13

fixed

浮点数按小数输出

14

 

boolalpha

以字母格式输入和输出布尔值

未设置

15

     (位组:有些标志位相互排斥,相互排斥的标记位属于同一位组,以便于对同一位组的标记位复位)

     2). 函数

fmtflags flags() const

获取当前格式变量

fmtflags flags (fmtflags fmtfl)

将格式变量设为fmtfl,并返回之前的格式变量

fmtflags setf (fmtflags fmtfl)

在原来格式基础上附加fmtfl,相当于flags(fmtfl|flags()).

fmtflags setf (fmtflags fmtfl, fmtflags mask);

将位组mask所包含的标记位清零,并置为fmtfl对应标记位的值,相当于flags((fmtfl&mask)|(flags()&~mask))

void unsetf (fmtflags mask)

清除位组mask的格式标记位

streamsize width() const;

获取当前域宽度

streamsize width (streamsize wide);

设置域宽度为wide

streamsize precision() const;

获取当前精度

streamsize precision (streamsize prec);

设置精度为prec

char fill() const;

获取当前的填充字符

char fill (char fillch)

设置输出宽度不满域宽时的填充字符为fillch,默认为空格

     注:在使用setf设置属于某一位组的标记位时,需要提供位组作为第二个参数来将其他互斥的标记位复位,否则可能会出现设置无效的现象.

    3). 使用2)的函数可以设置输入输出的格式,标准库还提供了"操纵符"(类似于函数)使得格式化输入输出更加方便,将操纵符作为<<和>>的右操作数使用可以直接设置输入输出格式,使用这些操纵符需要加头文件<iomanip>操纵符有:

操纵符

影响

用途

等价表示

flush

O

刷新流缓冲区

o.flush()

endl

O

插入换行符并刷新缓冲区

o.put(widen(‘\n’));

o.flush();

ends

O

插入串结束符

o.out(o.widen((‘\0’));

ws

I

抽取空白字符

 

boolalpha

I/O

设置bool型的输入输出格式

io.setf(ios_base::boolalpha)

noboolalpha

I/O

复位上述标志

io.unsetf(ios_base::boolalpha)

showbase

O

设置用于整数前缀的标志

o.setf(ios_base::showbase)

noshowbase

O

复位上述标志

o.unsetf(ios_base::showbase)

showpos

O

为非负整数设置产生’+’的标志

o.setf(ios_base::showpos)

noshowpos

O

复位上述标志

o.unsetf(ios_base::showpos)

showpoint

O

按精度输出浮点数(不够补0)

o.setf(ios_base::showpoint)

noshowpoint

O

复位上述标志

o.unsetf(ios_base::showpoint)

skipws

I

设置跳过空白字符的标志

i.setf(ios_base::skipws)

noskipws

I

复位上述标志

i.unsetf(ios_base::skipws)

uppercase

O

大写输出字母

o.setf(ios_base::uppercase)

nouppercase

O

复位上述标志

o.unsetf(ios_base::uppercase)

unitbuf

O

设置每次格式化输出后刷新输出的标志

o.setf(ios_base::unitbuf)

nounitbuf

O

复位上述标志

o.unsetf(ios_base::unitbuf)

internal

O

设置在指定内部节点填充字符的标志

o.setf(ios_base::interbal,ios_base::adjustfield)

left

O

设置左对齐标志

o.setf(ios_base::left,ios_base::adjustfield)

right

O

设置右对齐标志

o.setf(ios_base::right,ios_base::adjustfield)

dec

I/O

按十进制转换整数

io.setf(ios_base::dec,ios_base::basefield)

hex

I/O

按十六进制转换整数

io.setf(ios_base::hex,ios_base::basefield)

oct

I/O

按八进制转换整数

io.setf(ios_base::oct,ios_base::basefield)

fixed

O

设置浮点数按定点表示标志

o.setf(ios_base::fixed,ios_base::floatfield)

scientific

O

设置浮点数按科学表示法表示标志

o.setf(ios_base::scientific,ios_base::floatfield)

setiosflags(ios_base::fmtflags mask)

I/O

根据mask设置格式标志

io.setf(ios_base::fmtflags mask)

setiosflags(ios_base::fmtflags mask)

I/O

根据mask清除格式标志

io.unsetf(ios_base::fmtflags mask)

setbase(int base)

I/O

为整数表示设置基数

io.setf(base==8?ios_base::oct:base==10?ios_base::dec:base==16?ios_base::hex:ios_base::fmtflags(0),ios_base::basefield)

setfill(char c)

I/O

设置填充字符

io.fill(c)

setprecision(int n)

O

设置精度

io.precision(n)

setw(int n)

I/O

设置最小字宽

io.width(n)

     4). 正如以上所展示的,操纵符分为带参数和不带参数的,不带参数的操纵符本质上是具有特定参数和返回值类型的函数指针,带参数的操纵符本质上是重载了移位运算符的对象.

    自定义不带参数的操纵符,可以像这样:

ios_base& boolalpha(ios_base& strm){
    strm.setf(ios_base::boolaplha);
    return strm;
}
//ios_base是所有io流类的基类
View Code

    自定义带参数的操纵符,可以像这样:

class width{
public:
    explicit width(unsigned int i):i_(0){}
private:
    unsigned int i_;
    template<class charT,class Traits>
    friend base_ostream<char T,Traits>&   operator<<(basic_ostream<charT,Traits>&ib,const width&w){
        ib.width(w.i_);
        return ib;
}
View Code

    关于自定义操纵符的具体细节,详见《标准C++输入输出流与本地化》3.2

 

3. 文件打开方式标志

    1). 使用文件流类型时,可以在构造函数或open函数中指定打开方式,参数是ios_base::openmode类型(和iostate和fmtflags类似),以下是用于指定文件打开方式的标记位:

名称

作用

所占bit

app

向文件尾增加数据

1

ate

从文件尾部开始

2

binary

以二进制方式读写

3

in

以读方式打开文件

4

out

以写方式打开文件

5

trunc

清除文件内容(默认标志)

6

    2). 可以使用|同时按多个模式打开文件,但并不是所有的打开方式都可以组合,下表是合法的组合:

打开方式

作用

+ate标志

+binary标志

in

in|trunc

只读方式打开文件

只读方式打开文件设文件长度为0

初始文件位置指针在文件尾部

抑制转换

out

out|trunc

只写方式打开文件

只写方式打开文件并设文件长度为0

初始文件位置指针在文件尾部

抑制转换

out|app

追加,尽在文件尾写入

初始文件位置指针在文件尾部

抑制转换

in|out

读写均可

初始文件位置指针在文件尾部

抑制转换

int|out|trunc

读写均可并设文件长度为0

初始文件位置指针在文件尾部

抑制转换

    3). 其他注意事项

        1''. 输出文件流默认打开方式为ios_base::out|ios_base::trunc,输入文件流默认打开方式为ios_base::in|ios_base::trunc,也就是说,对于单项文件流trunc标志位是默认设置的,但双向文件流默认打开方式为ios_base:in|ios_base::out,默认不设置trunc标志位

        2''. ate(ate-end)和app,都是将文件指针定位在文件尾,不同之处在于,ate模式允许修改文件指针位置,app模式强制将指针定位到文件尾,即使修改指针位置也无效.

posted @ 2015-10-13 19:53  Reasno  阅读(2067)  评论(0编辑  收藏  举报