【C++】IO流
🌈欢迎来到C++专栏~~IO流
- (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort
- 目前状态:大三非科班啃C++中
- 🌍博客主页:张小姐的猫~江湖背景
- 快上车🚘,握好方向盘跟我有一起打天下嘞!
- 送给自己的一句鸡汤🤔:
- 🔥真正的大师永远怀着一颗学徒的心
- 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏
- 🎉🎉欢迎持续关注!

文章目录
- 🌈欢迎来到C++专栏~~IO流
- 一. C语言的输入与输出
- 二. 流是什么
- 三. C++IO流
- 🐋C++标准IO流
- ✨C++文件IO流
- ⚡以二进制的形式操作文件
- ⚡以文本的形式操作文件
- ⚡使用>>和<<对文件进行操作
- 四. stringstream的简单介绍
- 📢写在最后

一. C语言的输入与输出
C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()
- scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中
- printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)
C语言借助了相应的缓冲区来进行输入与输出

对输入输出缓冲区的理解:
- 可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。
- 可以使用这部分的内容实现“行”读取的行为,对于计算机而言是没有“行”这个概念,有了这部分,就可以定义“行”的概念,然后解析缓冲区的内容,返回一个“行”
二. 流是什么
“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且有方向性的数据的抽象描述。
C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”
流的特性:有序连续、具有方向性
三. C++IO流
C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类

从上图可以看出,cout、cerr、clog都是由ostream类实例化出的三个不同的对象,因此这三个对象基本没什么区别,只是应用场景不同。
🐋C++标准IO流
C++标准库提供了4个全局流对象(cin、cout、cerr、clog):
- 使用
cout进行标准输出,即数据从内存流向控制台(显示器) - 使用
cin进行标准输入,即数据通过键盘输入到程序中 - 使用
cerr进行标准错误的输出 - 使用
clog进行日志的输出
注意:
1、在使用cin、cout时必须要包含iostream文件,并引入std标准命名空间。
#include <iostream> //包含iostream文件
using namespace std; //引入std标准命名空间
int main()
{int a = 0;cin >> a;cout << a << endl;return 0;
}
或者指定cout和cin所属的命名空间
#include <iostream> //包含iostream文件
int main()
{int a = 0;std::cin >> a; //使用时指定所属命名空间std::cout << a << std::endl; //使用时指定所属命名空间return 0;
}
2、cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中提取。如果一次输入过多,则多余的数据会留在缓冲区以供之后提取,如果输入错了,必须在回车之前进行修改,回车键按下就无法进行修改了,只有把输入缓冲区中的数据取完后,才会要求输入新的数据
例如,对于以下代码,若在第一次输入时便以空格为分隔输入了两个数据,则在下一次需要提取数据的时候就直接从缓冲区进行提取
#include <iostream>
using namespace std;
int main()
{int a = 0, b = 0;cin >> a; //输入:10 20cout << a << endl;cin >> b; //直接从输入缓冲区提取cout << b << endl;return 0;
}
3、 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对应位置位(置1),程序继续
4、空格和回车都可以作为数据之间的分隔符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格无法用cin输入,字符串中也不能有空格,回车符也无法读入。
例如,我们使用cin无法将含空格的字符串"hello world"输入到string对象中。
#include <iostream>
#include <string>
using namespace std;
int main()
{string s;cin >> s; //输入:"hello world"cout << s << endl; //输出:"hello"return 0;
}
对于含有空格的字符串,我们需要使用getline函数进行读取,因为getline函数只有遇到’\n’才会停止读取。
#include <iostream>
#include <string>
using namespace std;
int main()
{string s;getline(cin, s); //输入:"hello world"cout << s << endl; //输出:"hello world"return 0;
}
5、cin和cout可以直接输入和输出内置类型的数据。因为标准库已经将所有内置类型的输入和输出进行了重载。
>>的运算符的重载:

<<的运算符的重载:

6、对于自定义类型,如果要支持cin和cout的标准输入输出,则需要对<<和>>进行重载。
例如,对于下面简单实现的日期类,在对<<和>>进行重载后就能够支持cin和cout的输入输出了。
#include <iostream>
using namespace std;
class Date
{friend istream& operator>>(istream& in, Date& d);friend ostream& operator<<(ostream& out, const Date& d);
public:Date(int year = 2021, int month = 1, int day = 1):_year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};
//对>>进行重载
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
//对<<进行重载
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "-" << d._month << "-" << d._day;return out;
}int main()
{Date d;cin >> d; //输入:2021 9 20cout << d << endl; //输出:2021-9-20return 0;
}
7、输入多个值,默认就是用空格或者换行分割的
int year, month, day;
cin >> year >> month >> day;
scanf("%d%d%d", &year, &month, &day);
//scanf("%d %d %d", &year, &month, &day);//不需要去加空格
如果输入的数值严格是20221128,可以用substr(),进行断句
//20230219string str;cin >> str;year = stoi(str.substr(0, 4));month = stoi(str.substr(4, 2));day = stoi(str.substr(6, 2));
8、在线OJ中的输入和输出
某些在线OJ题目是有多组测试用例对我们编写的代码进行测试的,对于这种题目,C语言通常采用的解决方式如下:
while (scanf("%d", &a) != EOF)
{//...
}
而在C++当中,我们一般采用的解决方式如下:
while (cin >> a)
{//...
}
C++中是运用了operator bool

✨C++文件IO流
C++根据文件内容的数据格式将文件分为二进制文件和文本文件,采用文件流对象操作文件的一般步骤如下:
1、定义一个文件流对象。
操作文件的类有以下三个:
| 类 | 对应操作场景 |
|---|---|
| ofstream | 只写 |
| ifstream | 只读 |
| fstream | 读和写 |
2、文件常见的打开方式如下:
| 打开方式 | 功能 |
|---|---|
| in | 以读的方式打开文件 |
| out | 以写的方式打开文件 |
| binary | 以二进制方式对文件进行操作 |
| ate | 输出位置从文件的末尾开始 |
| app | 以追加的方式对文件进行写入 |
| trunc | 先将文件内容清空再打开文件 |
3、对文件进行提取和插入操作的常用成员函数:
| 成员函数 | 功能 |
|---|---|
| put | 插入一个字符到文件 |
| write | 插入一段字符到文件 |
| get | 从文件提取字符 |
| read | read |
| tellg | 获取当前字符在文件当中的位置 |
| seekg | 设置对文件进行操作的位置 |
| >>运算符重载 | 将数据形象地以“流”的形式进行输入 |
| <<运算符重载 | 将数据形象地以“流”的形式进行输出 |
3、关闭文件
⚡以二进制的形式操作文件
二进制的读写:在内存中如何存储,就如何写到磁盘文件中
优点:快
缺点:写出去的内容看不见
🌈以二进制的形式对文件进行写入操作:
//配置文件
struct ServerInfo
{char _address[32]; //ipint _port; //端口
};//配置管理器
struct ConfigManager
{
public:ConfigManager(const char* filename = "test.txt"):_filename(filename){}//写void WriteBin(const ServerInfo& info){ofstream ofs(_filename, ios_base::out | ios_base::binary);ofs.write((char*)&info, sizeof(info));}//读void ReadBin(ServerInfo& info){ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs.read((char*)&info, sizeof(info));}private:string _filename; // 配置文件
};int main()
{//二进制写ServerInfo winfo = { "192.0.0.1", 12138 };ConfigManager cm;cm.WriteBin(winfo);//二进制读ServerInfo rinfo;ConfigManager cm;cm.ReadBin(rinfo);cout << rinfo._address << endl;cout << rinfo._port << endl;
}


此处要注意:
struct ServerInfo
{//char _address[32]; //ipstring _address; //此处用string会更好int _port; //端口
};
但会引发一个问题:打印出来的是乱码
其原因是:数据存在堆中,地址会更改

所以二进制读写的时候不适合用string,更多用的是数组来解决
文本读写就不限制,二者都可以用
⚡以文本的形式操作文件
文本读写:对象数据序列化字符串写出来,堵回来也是:字符串反序列化转成对象数据
优点:可以看得见写出去的是什么
缺点:存在一个转换的过程
//文本写
void WriteText(const ServerInfo& info)
{//c_str() : 将C++的string转化为C的字符串数组,c_str()生成一个const char *指针,指向字符串的首地址ofstream ofs(_filename, ios_base::out);ofs.write(info._address.c_str(), info._address.size());ofs.put('\n');const string str = to_string(info._port);ofs.write(str.c_str(),str.size());
}//文本读
void ReadText(ServerInfo& info)
{ifstream ifs(_filename, ios_base::in | ios_base::binary);char buff[128];ifs.getline(buff, 128);info._address = buff;ifs.getline(buff, 128);info._port = stoi(buff);
}
int main()
{//文本写ServerInfo winfo = { "192.0.0.1", 111111};ConfigManager cm;cm.WriteText(winfo);//文本读ServerInfo rinfo;ConfigManager cm;cm.ReadText(rinfo);cout << rinfo._address << endl;cout << rinfo._port << endl;
}
⚡使用>>和<<对文件进行操作
使用>>和<<运算符对文件进行读写操作,会变得很简单,也很形象
如果自定义类型也支持流插入、提取的重载
//对文件进行写入操作
void WriteTest(const ServerInfo& info)
{ofstream ofs(_filename, ios_base::out);ofs << info._address <<endl;ofs << info._port <<endl;ods << info._Date <<endl;//还可以直接流入自定义类
}
对文件的读取:
//对文件进行读取操作
void ReadFile()
{ifstream ifs("data.txt"); //定义文件流对象,并打开文件char data[100];ifs >> data; //文件数据“流入”字符串dataifs.close(); //关闭文件
}
四. stringstream的简单介绍
在C语言中,我们若是想要将一个整型变量的数据转化为字符串格式,有以下两种方法:
- 使用
itoa函数进行转化
int a = 10;
char arr[10];
itoa(a, arr, 10); //将整型的a转化为十进制字符数字存储在字符串arr当中
- 使用
sprintf函数进行转化
int a = 10;
char arr[10];
sprintf(arr, "%d", a); //将整型的a转化为字符串格式存储在字符串arr当中
虽然itoa函数和sprintf函数都能完成转化,但是在两个函数在转化时,都需要先给出保存结果的空间,而空间的大小是不太好界定的,除此之外,转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃。
在C++中,我们可以使用stringstream类对象来避开此问题。在程序当中如果想要使用stringstream,必须要包含头文件sstream。在该头文件下,有三个类:

此处重点讲解:序列化和反序列化结构数据
struct ChatInfo
{string _name; // 名字int _id; // id
};int main()
{// 结构信息序列化为字符串ChatInfo winfo = { "张三", 135246};ostringstream oss;oss << winfo._id << endl;oss << winfo._name << endl;string str = oss.str();cout << str << endl;//网络传输str ~//反系列化ChatInfo rInfo;istringstream iss(str);iss >> rInfo._id;iss >> rInfo._name;cout << "-------------------------------------------------------"<< endl;cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") "<< endl;cout << "-------------------------------------------------------"<< endl;return 0;
}

📢写在最后

相关文章:
【C++】IO流
🌈欢迎来到C专栏~~IO流 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤…...
【论文速递】ACL 2021-CLEVE: 事件抽取的对比预训练
【论文速递】ACL 2021-CLEVE: 事件抽取的对比预训练 【论文原文】:CLEVE: Contrastive Pre-training for Event Extraction 【作者信息】:Wang, Ziqi and Wang, Xiaozhi and Han, Xu and Lin, Yankai and Hou, Lei and Liu, Zhiyuan and Li, Peng and …...
《自动驾驶规划入门》专栏结语
一、 源起 2021年10月12日,化学工业出版社的金编辑根据博客中留下的微信号联系上我,问我有没有出书的想法。从小到大,书与文字在我心里是有着神圣地位的。我在“想试试”与“害怕做不好”这两种矛盾的心情中,还是先应了下来。签了…...
【数据结构与算法】2.八大经典排序
文章目录简介1.分析排序算法2.插入排序2.1.直接插入排序2.2.希尔排序3.选择排序3.1.直接选择排序3.2.堆排序3.2.1.堆的数据结构3.2.2.算法实现4.交换排序4.1.冒泡排序4.2.快速排序5.归并排序6.基数排序7.八大排序算法总结简介 排序对于任何一个程序员来说,可能都不会…...
Windows 免安装版mysql,快速配置教程
简单步骤 下载并解压mysql压缩包,把 “<mysql根目录>/bin” 路径添加到系统环境变量path中命令行执行 mysqld --initialize --console,初始化data目录(数据库表文件默认存放在" <mysql安装根目录>/data "目录下&#…...
空间误差分析:统一的应用导向处理(Matlab代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
【C++】引用、内联函数、auto关键字、范围for、nullptr
引用什么叫引用引用的特性常引用使用场景传值、传引用效率比较引用和指针的区别内联函数auto关键字(C11)基于范围的for循环(C11)指针空值nullptr(C11)引用 什么叫引用 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内…...
pytest数据驱动
文章目录一、数据驱动概念二、数据驱动yaml1、yaml的基本语法:2、yaml支持的数据格式:3、安装4、使用5、读取方法a、目录结构b、yaml文件c、测试方法d、测试用例e、测试结果三、数据驱动excel1、安装导入2、操作3、读取方法a、目录结构b、excel文件c、测…...
OSI七层网络模型
应用层 定义了各种应用协议规范数据格式:HTTP协议、HTTPS协议、FTP协议、DNS协议、TFTP、SMTP等等。 表示层 翻译工作。提供一种公共语言、通信。 会话层 1、可以从校验点继续恢复数据进行重传。——大文件 2、自动收发,自动寻址的功能。 传输层 1、…...
易基因|MeRIP-seq揭示m6A RNA甲基化通过调控组蛋白泛素化来促进癌症生长和进展:Cancer Res
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。2022年05月16日,《Cancer Res》杂志发表了题为“M6A RNA Methylation Regulates Histone Ubiquitination to Support Cancer Growth and Progression”的研究论文,该…...
Java 日期处理踩过的坑
前言 整理Java日期处理遇到过的问题,希望对大家有帮助 制作不易,一键三连,谢谢大家。 1.用 Calendar 设置时间的坑 反例: //提供者模式获取实例Calendar calendar Calendar.getInstance();//获取当前时间Date currentDate c…...
一文吃透 Spring 中的IOC和DI(二)
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
【期末指北】嵌入式系统——选择题(feat. ChatGPT)
作者|Rickyの水果摊 时间|2023年2月20日 基本信息 ☘️ 本博客摘录了一些 嵌入式系统 的 常见选择题,供有需求的同学们学习使用。 部分答案解析由 ChatGPT 生成,博主进行审核。 使用教材信息:《嵌入式系统设计与应…...
MyBatis-Plus——代码生成器(3.5.1+版本)
文章目录配置数据源配置(DataSource)全局配置(GlobalConfig)包配置(PackageConfig)策略配置(StrategyConfig)模板引擎配置(TemplateEngine)代码生成器测试样例…...
宁盾上榜第五版《CCSIP 2022 中国网络安全行业全景册》
2月1日,国内网络安全行业媒体Freebuf咨询正式发布《CCSIP(China Cyber Security Panorama)2022 中国网络安全行业全景册》第五版。宁盾作为国产身份安全厂商入驻身份识别和访问管理(SSO、OTP、IDaaS)及边界访问控制&am…...
【Linux系统】第七篇:Linux调试器gdb的使用
文章目录一、gdb简介二、gdb的安装三、gdb使用3.1、release和debug版本3.2、gdb基本使用命令1、启动gdb2、调试命令3、显示代码(list)4、断点命令(breakpoint)5 、变量命令(variable)6、特殊调试命令7、调用…...
Shell 特殊变量及其含义
shell是我们在linux下编写自动执行程序的常见脚本工具,通常会涉及到以下几个特殊变量,它们分别是:$#、$*、$、$?、$$。 变量含义$0当前脚本的文件名。$n(n≥1)传递给脚本或函数的参数。n 是一个数字,表示…...
LeetCode 2396. 严格回文的数字
如果一个整数 n 在 b 进制下(b 为 2 到 n - 2 之间的所有整数)对应的字符串 全部 都是 回文的 ,那么我们称这个数 n 是 严格回文 的。 给你一个整数 n ,如果 n 是 严格回文 的,请返回 true ,否则返回 fals…...
【RocketMQ】源码详解:Broker启动流程
Broker启动 入口: org.apache.rocketmq.broker.BrokerStartup#main broker的启动主要分为两部分:1.创建brokerController 2.启动brokerController。与平时进行业务开发时不同的是,这里的BrokerController相当于Broker的一个中央控制器类&…...
vue事件
1. 事件传参 <button click"clickEvt($event, 22)">点我</button>2. 事件修饰符 prevent:阻止默认事件stop:阻止事件冒泡(加到子元素)once:事件只触发一次capture:使用事件的捕获模…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
年度峰会上,抖音依靠人工智能和搜索功能吸引广告主
上周早些时候举行的第五届年度TikTok World产品峰会上,TikTok推出了一系列旨在增强该应用对广告主吸引力的功能。 新产品列表的首位是TikTok Market Scope,这是一个全新的分析平台,为广告主提供整个考虑漏斗的全面视图,使他们能够…...
鸿蒙APP测试实战:从HDC命令到专项测试
普通APP的测试与鸿蒙APP的测试有一些共同的特征,但是也有一些区别,其中共同特征是,它们都可以通过cmd的命令提示符工具来进行app的性能测试。 其中区别主要是,对于稳定性测试的命令的区别,性能指标获取方式的命令的区…...

