其他分享
首页 > 其他分享> > 第八章 IO库

第八章 IO库

作者:互联网

文章目录

IO库

8.1 IO类

三大IO类

w前缀的为对应的宽字符版本

cincoutcerrclog都有对应的宽字符版本wcinwcoutwcerrwclog

头文件和类的关系:

  1. iostream头文件

    1. istream,wistream
    2. ostream,wostream
    3. iostream,wiostream
  2. fstream头文件

    1. ifstream,wifstream
    2. ofstream,wofstream
    3. fstream,wfstream
  3. sstream头文件

    1. istringstream,wistringstream
    2. ostringstream,wostringstream
    3. stringstream,wstringstream

IO类之间的继承关系:

img

8.1.1 IO对象拷贝或赋值

注意:

  1. 流对象不能进行拷贝和赋值

  2. 读写IO对象会改变流的状态,因此传递和返回的流的引用不能是const的

8.1.2 条件状态

strm指的是任意一个IO类,置位指将标志数对应位设置为1,复位指将标志数对应位设置为0

条件状态描述
strm::iostateiostate是一种机器相关的类型,提供了条件状态的完整功能(VS2019中为int型)
strm::badbit用来指出流已崩溃4
strm::failbit用来指出一个IO操作失败了2
strm::eofbit用来指出流到达了文件末尾1
strm::goodbit用来指出流未处于错误状态。此值保证为零0
s.eof()若流s的eofbit置位,则返回true
s.fail()若流s的failbit或badbit置位,则返回true
s.bad()如流s的badbit置位,则返回true
s.good()如流s处于有效状态,则返回true
s.clear()将流s中所有状态位复位,将流的状态位设置为有效。返回void
s.clear(flags)根据给定的flags标志位,将流s中对应状态位复位。flags类型为strm::iostate。返回viod
s.setstate(flags)根据给定的flags标志位,将流s中对应状态位置位。flags类型为strm::iostate。返回void
s.rdstate()返回流的当前状态,返回值类型为strm::iostate

注意:一旦一个流发生错误,其上后续的IO操作都会失败。特别要注意的是读取文件的时候经常会读取到文件末尾,eoffail被置位,导致流失效

源文件中有一个**strm::iostate***(实质为int***)类型的_Mystate变量

_Mystate各个位的含义:

状态位badbitfailbiteofbit
位下标76543210

函数源代码:

(1)
iostate rdstate() const {
    return _Mystate;
}

(2)
bool good() const {
    return rdstate() == ios_base::goodbit;
}

bool  eof() const {
    return rdstate() & ios_base::eofbit;
}
//剩下的几个函数以此类推...

(3)
//由下面的函数可得,想要清除哪个位就将传入值中的那个位置0
void  clear(iostate _State = goodbit) {
      clear(_State);
}
    
void clear(iostate _State) {
      _State &= _Statmask;//_Statmask = 00010111
      _Mystate             = _State;
}

(4)
void setstate(iostate _State) { 
     clear(rdstate() | _State);
}

相信你已经明白了为什么

badbit值为4[00000100~b~],failbit的值为2[00000010b],efo的值为1[00000001~b~],goobit的值为0[00000000b]

8.1.3 管理输出缓冲

每个输入输出流对象都有自己的缓冲区

关联输入输出流

当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。

标准库将cin-cout关联,将cerr-cout关联

tie有两个版本,两个版本返回的都是指向改变之前关联的对象的指针

  1. 第一个版本:不接受参数
  2. 第二个版本:接受一个指向ostream的指针,将自己关联到此ostream

我们可以将一个istream对象关联到另一个ostream,也可以将一个ostream关联到另一个ostream

注意:每个流同时最多关联到一个流,但多个流可以同时关联到同一个ostream

8.2 文件输入输出

8.2.1 使用文件流对象

操作描述
fstream fstrm;创建一个未绑定的流。***fstream***是头文件fstream中定义的一个类型
fstream fstrm(s);创建一个fstream,并打开名为s的文件。s可以是string类型,或者是一个指向C风格字符串的指针。这些构造函数都是explicit的
fstream fstrm(s,mode);与前一个构造函数相同,但按指定mode打开文件
fstrm.open(s);打开名为s的文件,并将文件与fstrm绑定。返回void
fstrm.close();关闭与fstrm绑定的文件。返回void
fstrm.is_open();返回一个bool值,指出与fstrm关联的文件是否打开成功且尚未关闭

注意:

  1. 同一个流对象再次打开同一个文件会导致打开失败

  2. 不同对象可以同时打开同一个文件

  3. 当一个fstream对象被销毁时,close会自动被调用

8.2.2 文件模式

可选打开方式

mode描述
in以读方式打开
out以写方式打开
app每次写操作前均定位到文件末尾
ate每次文件打开后立即定位到文件末尾
trunc截断文件
binary以二进制方式进行IO

默认打开方式

对象默认打开方式
ifstreamin
ofstreamout
fstreamin 和 out

文件打开方式限制:

8.3 string流

操作描述
sstream strmstrm是一个为绑定stringstream对象。***sstream***是头文件sstream中定义的一个类型
sstream strm(s)strm是一个 sstream 对象,保存string s的一个拷贝。此构造函数是explicit的
strm.str()返回strm所保存的string的拷贝
strm.str(s)将string s拷贝到strm中。返回void

8.4 IO再探

8.4.1格式化输入输出

操纵符:一个操纵符是一个函数或是一个对象,会影响流的状态,并能作输入或输出运算符的运算对象

**注意:**当操作符改变流的格式状态时,通常改变后的状态对所有后续IO都生效

控制布尔值的格式

使用

std::cout<<boolalpha;

可以将布尔值以单词形式输出,要想调整回来,可以使用

std::cout<<noboolalpha;

指定整型值的进制

符号含义
dec十进制
oct八进制
hex十六进制

可使用 showbase显示不同进制的前缀,noshowbase取消不同进制的前缀显示

控制浮点数格式

可以调用IO对象的precision成员或使用setprecision操纵符来改变精度

默认情况下 ,浮点数按六位数字精度打印;

如果浮点数没有小数部分,则不会打印小数点;

根据浮点数的值选择打印成顶点十进制或科学计数法形式,标准库会选择可读性好的方式进行显示

操作符前面的*号表示此模式为默认模式

定义在iostream中的操纵符描述
boolalpha将true和false输出为字符串
*noboolalpha将true和false输出为1和0
showbase整数值输出表示进制的前缀
*noshowbase不生成表示进制的前缀
showpoint对浮点数总是显示小数点
*noshowpoint只有当浮点值包含小数部分时才显示小数点
showpos对非负数显示+[^对于unsigned类型不会显示+]
*noshowpos对非负数不显示+
uppercase在十六进制中打印0X,在科学计数法中打印E
*nouppercase在十六进制中打印0x,在科学计数法中打印e
*dec整型值显示为十进制
hex整型值显示为十六进制
oct整型值显示为八进制
left在值的右侧添加填充字符
right在值的左侧添加填充字符
internal子符号和值的中间添加填充字符
fixed浮点值显示为顶点十进制[^固定6位小数]
scientific浮点值显示为科学计数法
hexfloat浮点值显示为十六进制(C++11新特性)
*dehexfloat重置浮点数格式为十进制(C++11新特性)
unitbuf每次输出操作后都刷新缓冲区
*nounitbuf恢复正常的缓冲区刷新方式
*skipws输入运算符跳过空白符
noskipws输入运算符不跳过空白符[^对string对象无效]
flush刷新ostream缓冲区
ends插入空字符,然后刷新ostream缓冲区
endl插入换行,然后刷新ostream缓冲区

输出补白

定义在iomanip中的操纵符描述
setfill(ch)用ch填充空白
setprecision(s)将浮点数精度设置为n
setw(w)读或写值得宽度为w个字符
setbase(b)将整数输出为b进制

8.4.2未格式化的输入\输出操作

需要了解的是,缓冲区中会有一个指针,指向我们当前操作的字符,读取或输出缓冲区内容时,指针会自动++

单字节操作

单字节操作函数描述
is.get(ch)从istream is读取下一个字节存入字符ch中。返回is
os.put(ch)将字符ch输出到ostream os。返回os
is.get()将is的下一个字符作为int返回
is.putback(ch)将流指针后移一个字节。返回is
is.unget()将流指针后移一个字节。返回is
is.peek()将下一个字节作为int返回,但不移动指针位置

函数peek()和无参版本的get版本都以int类型从输入流返回一个字符。

这些函数返回一个int的原因是:可以返回文件尾标志。我们使用char范围中的值来表示一个真实字符,因此,取值范围中没有额外的值可以用来表示文件尾

多字节操作

多字节操作函数描述
is.get(sink,size,delim)从is中读取最多size个字节,并保存在字符数组中,字符数组的起始地址右sink给出。读取过程直至遇到字符delim或读取了size个字节或遇到文件尾时停止。如果遇到了delim,则将其留在输入流中,不读取出来存入sink
is.getline(sink,size,delim)与接受三个参数的get版本类似,但会读取并丢弃delim
is.read(sink,size)读取最多size个字节,存入字符数组sink中。返回is
is.gcount()返回上一个未格式化读取操作从is读取的字节数
os.write(source)将字符数组source中的最多size个字符写入os。返回os
is.ignore(size,delim)忽略最多size个或者忽略delim前的所有字符(包括delim),哪个先满足就按哪个执行

注意:

  1. is.get()和is.getline()函数会读取size-1个字节,并自动把字符数组最后一个字节赋值为’\0’,而read函数会读取size个字节,不会自动把字符数组最后一个字节赋值为’\0’,需要我们特别注意,否则将有可能导致错误
  2. 在一台char被实现为unsignend char类型的机器上,下面的循环永远不会停止:*
char ch;
while((ch = cin.get()) != EOF){
    cout.put(ch);
}
//原因如下
//EOF = -1  ->源码:1...00000001  ->反码:1...11111110  ->补码:1...11111111
//ch取得EOF低八位,所以 ch = 11111111(二进制) -> ch = 255,而EOF = -1,所以永远不会相等

8.4.3 流随机访问

随机IO本质上是依赖于系统的,为了理解如何使用这些特性,你必须查询系统文档

注意:istream和ostream类型通常不支持随机访问

后缀g可以理解为get,p可以理解为put

随机访问函数描述
tellg()返回一个输入流中(tellg)标志的当前位置
tellp()返回一个输出流中(tellp)标志的当前位置
seekg(pos)在一个输入流中将标志重定位到给定的绝对地址。pos通常是前一个tellg返回的值
seekp(pos)同上,只不过运用的是输出流
seekg(off,from)在一个输入流将标志定位到from之前或之后off个字符(off表示后移,off为负表示前移)
seekp(off,from)同上,…
from的值描述
beg流开始位置
cur流当前位置
end流结尾位置

注意:标准库区分seek和tell函数的gp版本这一特性可能会导致误解。即使标准库进行了区分,但它在一个流中之维护单一的标志——并不存在独立的读标志和写标志

标签:返回,文件,ch,IO,字符,第八章,strm
来源: https://blog.csdn.net/m0_52760964/article/details/119666713