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

dec10进制输入/输出

dec

10
oct8进制输入/输出11
hex16进制输入/输出12
floatfieldscientific浮点数按科学计数法输出无,由浮点数量级决定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)的函数可以设置输入输出的格式,标准库还提供了"操纵符"(类似于函数)使得格式化输入输出更加方便,将操纵符作为<<和>>的右操作数使用可以直接设置输入输出格式,使用这些操纵符需要加头文件操纵符有:

操纵符 影响 用途 等价表示
flush O 刷新流缓冲区 o.flush()
endl O 插入换行符并刷新缓冲区 o.put(widen(‘n’));

o.flush();

endsO插入串结束符o.out(o.widen((‘’));
wsI抽取空白字符
boolalphaI/O设置bool型的输入输出格式io.setf(ios_base::boolalpha)
noboolalphaI/O复位上述标志io.unsetf(ios_base::boolalpha)
showbaseO设置用于整数前缀的标志o.setf(ios_base::showbase)
noshowbaseO复位上述标志o.unsetf(ios_base::showbase)
showposO为非负整数设置产生’+’的标志o.setf(ios_base::showpos)
noshowposO复位上述标志o.unsetf(ios_base::showpos)
showpointO按精度输出浮点数(不够补0)o.setf(ios_base::showpoint)
noshowpointO复位上述标志o.unsetf(ios_base::showpoint)
skipwsI设置跳过空白字符的标志i.setf(ios_base::skipws)
noskipwsI复位上述标志i.unsetf(ios_base::skipws)
uppercaseO大写输出字母o.setf(ios_base::uppercase)
nouppercaseO复位上述标志o.unsetf(ios_base::uppercase)
unitbufO设置每次格式化输出后刷新输出的标志o.setf(ios_base::unitbuf)
nounitbufO复位上述标志o.unsetf(ios_base::unitbuf)
internalO设置在指定内部节点填充字符的标志o.setf(ios_base::interbal,ios_base::adjustfield)
leftO设置左对齐标志o.setf(ios_base::left,ios_base::adjustfield)
rightO设置右对齐标志o.setf(ios_base::right,ios_base::adjustfield)
decI/O按十进制转换整数io.setf(ios_base::dec,ios_base::basefield)
hexI/O按十六进制转换整数io.setf(ios_base::hex,ios_base::basefield)
octI/O按八进制转换整数io.setf(ios_base::oct,ios_base::basefield)
fixedO设置浮点数按定点表示标志o.setf(ios_base::fixed,ios_base::floatfield)
scientificO设置浮点数按科学表示法表示标志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). 正如以上所展示的,操纵符分为带参数和不带参数的,不带参数的操纵符本质上是具有特定参数和返回值类型的函数指针,带参数的操纵符本质上是重载了移位运算符的对象.

自定义不带参数的操纵符,可以像这样:
C++:IO标志位C++:IO标志位

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

View Code
自定义带参数的操纵符,可以像这样:
C++:IO标志位C++:IO标志位

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

  1. 文件打开方式标志

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模式强制将指针定位到文件尾,即使修改指针位置也无效.
原文链接: https://www.cnblogs.com/reasno/p/4875656.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/222996

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午11:56
下一篇 2023年2月13日 上午11:56

相关推荐