【C++】IO流
IO流
- 一、C语言的输入输出
- 二、流的概念
- 三、C++ IO流
- 1. C++标准IO流
- 2. C++文件IO流
- 四、stringstream 的简单介绍
- 1. 将数值类型数据格式化为字符串
- 2. 字符串拼接
- 3. 序列化和反序列化结构数据
一、C语言的输入输出
C语言中我们用到的最频繁的输入输出方式就是 scanf () 与 printf() :
- scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。
- printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。
注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来进行输入与输出。如下图所示:
二、流的概念
“流” 即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据( 其单位可以是bit,byte,packet )的抽象描述。
C++ 流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”。它的特性是:有序连续、具有方向性。为了实现这种流动,C++ 定义了 I/O 标准类库,这些每个类都称为流/流类,用以完成某方面的功能。
三、C++ IO流
C++ 系统实现了一个庞大的类库,其中 ios 为基类,其他类都是直接或间接派生自 ios 类,如下图:
1. C++标准IO流
C++ 标准库提供了4个全局流对象 cin、cout、cerr、clog,使用 cout 进行标准输出,即数据从内存流向控制台(显示器)。使用 cin 进行标准输入即数据通过键盘输入到程序中,同时 C++ 标准库还提供了 cerr 用来进行标准错误的输出,以及 clog 进行日志的输出,从上图可以看出,cout、cerr、clog 是 ostream 类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同。
在使用时候必须要包含文件并引入 std 标准命名空间。
注意:
- cin 为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。
- 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字 state 中对应位置位(置1),程序继续。
- 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格(ASCII码为32)无法用 cin 输入,字符串中也不能有空格。回车符也无法读入。
- cin 和 cout 可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了。
- 对于自定义类型,如果要支持 cin 和 cout 的标准输入输出,需要对 > 进行重载。
- 在线 OJ 中的输入和输出:
-
对于 IO 类型的算法,一般都需要循环输入;
-
输出:严格按照题目的要求进行,多一个少一个空格都不行;
-
连续输入时,vs 系列编译器下在输入 ctrl+Z 时结束
// 单个元素循环输入 while (cin >> a) { // ... } // 多个元素循环输入 while (c >> a >> b >> c) { // ... } // 整行接收 while (cin >> str) { // ... }
- istream 类型对象转换为逻辑条件判断值
例如文档:istream 流提取重载 和 operator bool() 重载
实际上我们看到使用 while(cin>>i) 去流中提取对象数据时,调用的是 operator>>,返回值是 istream 类型的对象,那么这里可以做逻辑条件值,源自于 istream 的对象又调用了operator bool(),operator bool() 调用时如果接收流失败,或者有结束标志,则返回 false.
例如下面的日期类,当我们输入 _year 为 0 时,结束循环:
class Date { friend ostream& operator > (istream& in, Date& d); public: Date(int year = 1, int month = 1, int day = 1) :_year(year) , _month(month) , _day(day) {} operator bool() { // 这里是随意写的,假设输入_year为 0,则结束 if (_year == 0) return false; else return true; } private: int _year; int _month; int _day; }; // 流提取重载 istream& operator >> (istream& in, Date& d) { in >> d._year >> d._month >> d._day; return in; } // 流插入重载 ostream& operator