加载中...
“流”的基本概念与应用
第1节:“流”的基本概念与应用
第2节:C++和C标准输入输出同步
第3节:C++和C的格式化输入输出
第4节:重温文件流和字符串流
第5节:为自定义类型重载流操作
第6节:三大关联知识点综合强化复习
第7节:从零开始,实现日志流
第8节:“我的日志流”终版
课文封面

本课含两个视频;第一个用以了解流的本质是队列,懂得区分输入、输出流;理解“抽象流”和“具体流”之分,并掌握通过面向“抽象流”面程以获得代码更好的适用性;第二个通过一个简单的日志功能的项目演化过程,实践前面所学。

1. “流” 的目的与本质

流的目的是为了解耦。

1.1 “耦合 / Coupling ”是什么?

不必要的关系

事物之间存在不必要的关系,就叫耦合;这种关系往往会引发双方进一步产生额外的牵制关系。

1.2 “流”解的是谁和谁的耦合?

以“面对面”的方式(有时还加上“一对一”的关系)进行数据交接的双方,很容易产生时间、地点、方式上的耦合。

以生活中的事情为例,假设要求快递一定要将货物面对面的交给买家,甚至要求买家签字(其实,最早的快递,基本就是如此),那么,就至少有如下耦合:

  1. 时间耦合:不是你等快递员,就是快递员等你;
  2. 地点耦合:收货地点是公司,可是今天你请假在家;收货地点是家,可是今天你996;
  3. 方式耦合:不仅要当面交接,如买家因种种原因拒签,则容易引发双方纠纷;

程序中的数据交接,如果也只能走“面对面”这一种形式,同样容易引发各种耦合。因此,想要解除或降低A和B之间因数据交接产生的耦合,方法是在二者之间塞入一个第三方:数据缓存区。这各现实上快递和收货人之间的解耦的本质是一样:东西放在楼下小店、放在菜鸟驻站、放在丰巢……

1.3 🎞️视频一:“流” 的基本概念

1.4 流的本质是队列

学完视频之后,我们了解到以下几点:

  1. 流的本质是队列,即:一个带有顺序保障的数据缓存区;
  2. 依据程序的视角,流区分为输入流和输出流;
  3. 向程序输入数据的流,叫输入流;程序向之输出数据的流,叫输出流;
  4. “ostream” 代表抽象的、泛指的输出流,文件输出流 “ofstream”和字符串输出流 “ostringstream” 都是输出流;
  5. “istream” 代表抽象的,泛指的输入流,文件输入流“ifstream”和字符串输入流“istringstream”都是输入流;
  6. 文件流可视为“外存流”,具有外存的特点:可理解为永久存储,但读写较慢;
  7. 字符串流可视为“内存流”,具有内存的特点:不能永远存储,但读写更快;
  8. 如上所述,文件流和内存流都可以既是输入流,也是输出流。

2. 面向抽象流的编程实例

请观看视频二,相关代码见后。

2.1 🎞️视频二:日志输出的5个版本

2.2 版本1:手工写日志

#include <iostream> using namespace std; int main() { cout << "【信息】:" << "即将输出你好世界!" << endl; cout<<"你好,世界!" << endl; cout << "【信息】:" << "完成输出你好世界!" << endl; cout << "【信息】:" << "终于不辱使命,即将全身而退。" << endl; }

2.3 版本2:使用函数写日志

#include <iostream> #include <string> using namespace std; void OutputDebugInfo(std::string const& debug_info) { cout << "【信息】:" << debug_info << endl; } int main() { OutputDebugInfo("即将输出你好世界!"); cout<<"你好,世界!" << endl; OutputDebugInfo("完成输出你好世界!"); OutputDebugInfo("终于不辱使命,即将全身而退。"); }

2.4 版本3:使用文件输出流

#include <iostream> #include <string> #include <fstream> using namespace std; void OutputDebugInfo(ofstream& ofs, std::string const& debug_info) { ofs << "【信息】:" << debug_info << endl; } int main() { ofstream ofs ("log.txt"); OutputDebugInfo(ofs, "即将输出你好世界!"); cout<<"你好,世界!" << endl; OutputDebugInfo(ofs, "完成输出你好世界!"); OutputDebugInfo(ofs, "终于不辱使命,即将全身而退。"); }

2.5 版本4:使用抽象输出流

#include <iostream> #include <string> #include <fstream> using namespace std; void OutputDebugInfo(ostream& os, std::string const& debug_info) { os << "【信息】:" << debug_info << endl; } int main() { ofstream ofs ("log.txt"); OutputDebugInfo(ofs, "即将输出你好世界!"); cout<<"你好,世界!" << endl; OutputDebugInfo(ofs, "完成输出你好世界!"); OutputDebugInfo(cout, "终于不辱使命,即将全身而退。"); }

2.6 版本5:使用字符串流

#include <iostream> #include <string> #include <fstream> #include <sstream> using namespace std; void OutputDebugInfo(ostream& os, std::string const& debug_info) { os << "【信息】:" << debug_info << endl; } int main() { ofstream ofs ("log.txt"); OutputDebugInfo(ofs, "即将输出你好世界!"); cout<<"你好,世界!" << endl; ostringstream oss; OutputDebugInfo(oss, "估计要出错了哦……"); OutputDebugInfo(oss, "好像还真的是出错了!"); OutputDebugInfo(oss, "原来,并没有出错啊"); cout << oss.str() << endl; OutputDebugInfo(ofs, "完成输出你好世界!"); OutputDebugInfo(cout, "终于不辱使命,即将全身而退。"); }