目录
引入
在原先c语言中,我们一般使用scanf和printf来进行输入输出,并且有输入输出缓冲区的存在
- (这里的"代码"实际上应该是底层中的内存)
输入输出缓冲区的作用
- 它可以让原本没有"行"概念的计算机在解析缓冲区内容后,返回一个"行"
- 不同的操作系统和环境可能有不同的底层 I/O 实现方式,但通过使用标准库函数和输入输出缓冲区,程序员可以将底层的实现细节隐藏起来,使程序在不同平台上运行更加可靠和可移植
- 通过在内存中累积一定量的数据,程序可以减少频繁的 I/O 操作,从而提高效率
而这种数据运输的过程,被比喻为"流"
流
引入
介绍
流是一种抽象概念
- 它表示数据的有序序列,这些数据可以被读取、写入或处理,数据可以是各种类型的
- 这些序列形成一个数据传输通道(可以理解为是一个管道),程序可以逐个字节或块地读取和写入数据,而不必关心数据的来源或去向
- 它可以描述 数据在[程序]和[外部源/目标]之间的传输
分类
流分为两种
- 输入流用于从[外部源]读取数据存入[计算机内部]
- 输出流用于将数据写入[外部设备]
c++io流
引入
- C语言的标准库提供的用于处理输入输出的函数,可以被认为是操作流的接口
- 而在C++中,也引入了面向对象的流库,其中流对象成为了数据输入和输出的关键接口
介绍
- 其中,流被抽象成类的对象
c++的io流库形成了一个庞大的继承体系
- 最基本的基类是ios_base,在这之上派生出各种类
一般我们是使用iostream中的cin,cout全局流对象进行输入输出操作
- 其中c表示console,意思是控制台
在c语言中:
- 有fscanf/fprintf等f系列函数,用于处理文件
- 有sscanf/sprintf等s系列函数,用于处理字符串
c++也沿用了这个设计:
- fstream包括了对文件进行io的函数
- sstream包括了对字符串进行io的函数
为什么要把流进行面向对象的设计呢?
在c中,无法直接向自定义类型输入输出,它提供的接口都是针对内置类型
- 所以在c++中增加了[自定义类型]直接和控制台交互的操作(也就是面向对象的设计)
- 这样把流对象化,可以让"流"这个概念更加形象
- 流 -- cin>>a ,把输入流的内容流入到a中; cout<<a,把a流入到输出流中
原理
实际上,自定义类型的io操作是通过重载运算符<<和>>实现的
- 并且,c++中的cin,cout不是可以自动识别类型吗?它实际上就是通过函数重载实现的
使用的注意点
[输入的数据类型必须与[要提取的数据类型]一致
- 否则出错
出错
- 只是在流的[状态字state]中对应位置1,然后程序继续
空格和回车都可以作为数据之间的分格符
- 所以多个数据可以在一行输入,也可以分行输入
- 如果需要读取整个行,包括空格,可以使用getline函数
istream类型对象->bool值
引入
多行输入可以用while(cin>>n)来实现,为什么呢?
- 是因为通过重载的>>,返回一个cin对象的引用
- 而这个引用可以作为while的条件,也就意味着cin可以被转换为bool值
这个转换依靠了这个函数:
- 这个函数就是c++中的转换运算符
转换运算符
用于定义 类类型 到 另一种数据类型 的自定义转换的特殊成员函数
- 格式 : operator+类型名
class MyClass { public: operator int() { return someValue; } private: int someValue; };
class MyClass { public: operator AnotherClassType() { AnotherClassType result; // Define the logic to create and initialize result return result; } };
调用过程
所以一个简单的while(cin>>n)实际的调用过程:
- cin调用operator>>,去流中提取数据
- 然后返回一个istream对象
- 这个对象调用operator bool()
- 如果接收流失败,或者有结束标志,则返回false ; 其他返回true
- 然后这个bool值作为while的判断条件