C++——IO流

目录

一,C语言的输入与输出

二,流是什么

三,C++标准IO流

3.1 四个全局流对象

 3.2 OJ题中的输入和输出

 3.3 自定义类型重载输入和输出

四,C++文件IO流

4.1 C++文件操作步骤

4.1.1 操作文件的类

4.1.2 文件打开方式

4.1.3 文件操作常用函数

4.1.4 演示

4.2 以二进制和文本方式读写演示代码

4.3 二进制和文本读写优缺点

五,stringstream介绍

5.1 C语言整形转字符串

5.2 stringstream

5.2.1 将数值类型数据格式化为字符串

5.2.2 字符串拼接

5.2.3 序列化和反序列化

5.3 注意事项


一,C语言的输入与输出

C语言中我们最常用的输入输出方式为scanf()和printf()

①scanf()表示从标准输入设备(键盘等)读取数据,并将值存放在变量中。

②printf()表示将指定的内容格式化输出到标准输入设备(屏幕等)。

C语言借助了相应的缓冲区来进行输入和输出,如下图:

 对缓冲区的理解:

可以屏蔽调低级IO的实现,因为低级IO的实现依赖操作系统本身内核的实现,所以如果能屏蔽这部分的差异,可以很容易写出可移植性高的程序

可以使用这部分的内容实现“行”读取的行为,对于计算机本身而言是没有“行”这个概念的,具体细节我们到Linux系统编程的文件系统章节再细讲

二,流是什么

“流”即流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据的抽象描述

C++流指的是信息从外部设备向计算机内部输入和从内存向外部输出设备输出的过程。

流的特性是:有序连续,具有方向性

所以为了实现这种流动,C++定义了IO标准类库,这些每个类都称为流或者流类。

三,C++标准IO流

C++系统实现了一个庞大的类库,其中ios为基类,其他类全是直接或间接的是继承ios的子类

3.1 四个全局流对象

C++标准库提供了4个全局流对象cin,cout,cerr,clog。使用cout进行标准输出,即数据从内存流向控制台(屏幕)。使用cin进行标准输入即数据从外部设备(键盘)输入到程序中,同时C++标准库还提供了cerr用来进行标准错误输出,以及clog日志输出。但是从上图可以看出,cout,cerr,clog是ostream类的三个不同的对象,所以这三个基本无区别,至少应用场景不同

注意:

①cin为缓冲流。键盘输入的数据都把偶从你在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,数据会存在缓冲区中按需被提取。如果输入错了,必须在回车之前修改,因为流是单向的。而且只有把输入缓冲区的数据读取完后,才会要求输入新的数据

int main()
{int a, b;cin >> a;cout << a << endl;cin >> b;cout << b << endl;return 0;
}

输入的数据类型必须与要提取的数据类型一致,否则报错

③空格和回车都可以作为数据之间的分隔符,所以多个数据可以在一行输入,也可以分行输入,但是如果是字符串和字符型,则空格(ASCLL为32)无法用cin输入,字符串内也不能用空格。

int main()
{string s1;cin >> s1; //如果输入hello world,字符串里面包含空格,则下面打印的时候只打印hellocout << s1 << endl;return 0;
}

 所以对于有空格的字符串,我们用getline函数读取,这个函数遇到'\n'才会停下来

int main()
{string s2;getline(cin, s2);cout << s2 << endl;return 0;
}

④C++标准库中的cin和cout可以直接输入和输出所有内置类型数据,因为标准库已经重载了所有的内置类型的输入和输出,对于自定义类型则需要自己重载输入输出

void main()
{//int i = 1;//double j = 2.2;//cout << i << j << endl;//其实这里的自动识别类型就是operator<<和重载//2022 11 28//输入多个值,默认都是用空格或者换行分割int year, month, day;cin >> year >> month >> day;scanf_s("%d%d%d", &year, &month, &day);//scanf("%d %d %d", &year, &month, &day); //不需要去加空格//20240410 强制要求这样输入scanf_s("%4d%2d%2d", &year, &month, &day);string str;cin >> str;//利用分割函数可以把字符串分割出来year = stoi(str.substr(0,4));month = stoi(str.substr(4,2));day = stoi(str.substr(6,2));
}

 3.2 OJ题中的输入和输出

对于IO类型的算法,一般需要循环输入,而且输出也是按照题目的要求严格进行。

//	OJ题要输入多组测试用例
void main()
{int year, month, day;string str;//ctrl+c 9号信号强杀//ctrl+z+换行 流对象提取到结束标志//istream& operator>> (istream& is, string& str);  while (cin >> str){//为什么istream的cin对象可以转bool//因为istream有explicit operator bool() const;//支持自定义类型转内置类型year = stoi(str.substr(0, 4));month = stoi(str.substr(4, 2));day= stoi(str.substr(6, 2));cout << year << "年" << month << "月" << day << "日" << endl;}
}

 3.3 自定义类型重载输入和输出

class Date
{friend ostream& operator << (ostream& out, const Date& d);friend istream& operator >> (istream& in, Date d);
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){}operator bool(){if (_year == 0)return false;elsereturn true;}
private:int _year;int _month;int _day;
};istream& operator >> (istream& in, Date d)
{in >> d._year >> d._month >> d._day;return in;
}//不仅仅针对ostream,ofstream和stringstream也可以用,因为用的是继承体系
ostream& operator << (ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}void main()
{//自动识别类型的本质--函数重载//内置类型可以直接使用--因为库里面ostream类型已经实现了int i = 1;double j = 2.2;cout << i << endl;cout << j << endl;// 自定义类型则需要我们自己重载<< 和 >>Date d(2022, 4, 10);cout << d;while (d){cin >> d;cout << d;}
}

四,C++文件IO流

4.1 C++文件操作步骤

4.1.1 操作文件的类

操作
fstream读和写
ifstream只读
ofstream只写

4.1.2 文件打开方式

方式功能
in以读的方式打开文件
out以写的方式打开文件
binary以二进制的方式对文件进行操作
ate从文件的末尾开始输出
app对文件进行追加写入
trunc将文件清空再打开

4.1.3 文件操作常用函数

函数功能
put插入一个字符到文件
write插入字符串到文件
get从文件提取字符
read从文件提取多个字符
tellg获取当前字符在文件中的位置
seekg设置对文件进行操作的位置
<<运算符重载将数据“流”输入
>>运算符重载将数据“流”输出

4.1.4 演示

//fstream文件流
void main1()
{std::ofstream ofs("test.txt", ofstream::out | ofstream::app);ofs << "hello world";ofs << "hello world"; //把字符串写到文件里去
}void main2()
{ifstream ifs("test.txt");//fscanf("%d%s%f",);C语言将文档内容读到变量里的方法//读int i;string s;double d;Date de;//C++的优势,可以读自定义类型,前提是自定义对象重载了>>ifs >> i >> s >> d >> de;	
}

4.2 以二进制和文本方式读写演示代码

struct ConfigManager
{
public:ConfigManager(const char* filename = "server.config"):_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));}//C语言的方式 -- 太复杂,不好搞/*void WriteText(const ServerInfo& info){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);}*///我们直接用C++重载的流操作符void WriteText(const ServerInfo& info) //文本写{ofstream ofs(_filename, ios_base::out);ofs << info._address << endl;ofs << info._port << endl;ofs << info._date << endl;}void ReadText(ServerInfo& info) //文本读{ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs >> info._address >> info._port >> info._date;}private:string _filename; // 配置文件
};void main1()
{//二进制写进去//ServerInfo winfo = { "127.0.0.1",888 };ServerInfo winfo = { "https://legacy.cplusplus.com/reference/istream/istream/read/",888 };ConfigManager cm;cm.WriteBin(winfo);//上面的执行一次就写一次//二进制读ServerInfo rinfo;cm.ReadBin(rinfo);cout << rinfo._address << endl;//读不了地址,因为写入时创建了指针,写完后析构了,指针变成野指针,所以二进制写入不敢用string,最好用数组cout << rinfo._port << endl;   //ServerInfo为char数组时不崩,是string时就崩
}void main2()
{// 文本写出去//ServerInfo winfo = { "127.0.0.1", 888};ServerInfo winfo = { "https://legacy.cplusplus.com/reference/istream/istream/read/", 888, { 2022, 11, 30 } };ConfigManager cm;cm.WriteText(winfo);// 文本的读ServerInfo rinfo;cm.ReadText(rinfo);cout << rinfo._address << endl;cout << rinfo._port << endl;cout << rinfo._date << endl;
}

4.3 二进制和文本读写优缺点

二进制读写:再内存如何存储,就如何写道磁盘文件

优点:快

缺点:写入内容不可见,需要二进制读的时候才能看见

文本读写:对象数据序列化字符串写出来,读回来也是字符串,反序列化转成对象数据

优点:可以看见写出去的是什么

缺点: 存在转换过程,要慢一些

五,stringstream介绍

5.1 C语言整形转字符串

在C语言中,如果想要将一个整形变量的数据转化为字符串格式,我们可以使用:①itoa()函数  ②sprintf()函数

但是两个函数在转化时,都得先给出保存结果的空间,但是所需空间的大小不好给定,而且转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃

int main()
{int n = 123456789;char s1[32];_itoa(n, s1, 10);char s2[32];sprintf(s2, "%d", n);char s3[32];sprintf(s3, "%f", n);return 0;
}

5.2 stringstream

标准库三个类:istringstream,ostringstream和stringstream,分别用来进行流的输入,输出和输入输出操作。

stringstream主要可以用来做下面几种事

5.2.1 将数值类型数据格式化为字符串

#include<sstream>
int main()
{int a = 1234;string sa;stringstream s;s << a; //输入流输入int as >> sa; //将a输出到string sa中cout << sa << endl;s.str(""); //将stringstream底层管理的string对象设置为空字符串s.clear(); //清楚上次转换状态double b = 3.14;s << b;sa = s.str();cout << sa << endl;
}

5.2.2 字符串拼接

#include <sstream>
int main()
{string rets;stringstream s;s << "hello" << "2024"; //将多个字符串放入stringstream中s >> rets; //方式一获取cout << rets << endl;s.str(""); //将stringstream底层管理的string对象设置为空字符串s.clear(); //将上次转换状态清空掉s << "You" << " " << "looks" << " " << "good"; //将多个字符串放入stringstream中rets = s.str(); cout << rets << endl;return 0;
}

5.2.3 序列化和反序列化

struct ChatInfo
{string _name; // 名字int _id;      // idDate _date;   // 时间string _msg;  // 聊天信息
};//stringstream字符串流运用场景
void main()
{// 序列化 -- 不管你是整形还是对象,都给你转成字符串ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" };//ostringstream oss;stringstream oss;oss << winfo._name << endl;oss << winfo._id << endl;oss << winfo._date << endl;oss << winfo._msg << endl;string str = oss.str();cout << str << endl;// 网络传输str,另一端接收到了字符串串信息数据// 反序列化 -- 解析上面的转换后的数据ChatInfo rInfo;//istringstream iss(str);stringstream iss(str);iss >> rInfo._name;iss >> rInfo._id;iss >> rInfo._date;iss >> rInfo._msg;cout << "----------------------------------" << endl;cout << rInfo._date << endl;cout << rInfo._name << "[" << rInfo._id << "]:>" << rInfo._msg << endl;
}

5.3 注意事项

①stringstream实际是在底层维护了一个string的对象来保存结果

②多次数据类型转化时,需要clear()来清空上次转换,下次转换才能正常转换,但是clear()不会将string对象清空

③可以使用s.str("");将底层string设置为空字符串

④可以使用s.str() 让stringstream返回底层的string对象

⑤stringstream使用string类代替字符数组,可以避免缓冲区溢出的情况,而且会参数类型进行推演,不需要格式化控制,也不会出现格式化失败的风险,因此使用更安全,也更方便

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/303954.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据下载】SODA数据更新至2022并教学下载

【数据下载】SODA数据更新至2022并教学下载 我为什么那么喜欢使用SODA数据&#xff1f; 就是三维网格化的数据&#xff0c;好用。 但是需要高分辨率还是需要找别的。 以前分享过SODA数据下载&#xff0c;但上次版本过于凌乱。因此重新借助更新再分享一次&#xff0c;不为过。…

前端mock数据——使用mockjs进行mock数据

前端mock数据——使用mockjs进行mock数据 一、安装二、mockjs的具体使用 一、安装 首选需要有nodejs环境安装mockjs&#xff1a;npm install mockjs 若出现像上图这样的错&#xff0c;则只需npm install mockjs --legacy-peer-deps即可 src下新建mock文件夹&#xff1a; mo…

Python | 超前滞后分析

Nino SST Indices (Nino 12, 3, 3.4, 4; ONI and TNI) 有几个指标用于监测热带太平洋&#xff0c;所有这些指标都是基于海表温度(SST)异常在一个给定的区域的平均值。通常&#xff0c;异常是相对于30年的周期来计算的。厄尔尼诺3.4指数(Nio 3.4 index)和海洋厄尔尼诺指数(Ocea…

【JavaWeb】Day39.MySQL概述——数据库设计-DQL(二)

数据库设计-DQL 聚合函数 聚合函数查询就是纵向查询&#xff0c;它是对一列的值进行计算&#xff0c;然后返回一个结果值。&#xff08;将一列数据作为一个整体&#xff0c;进行纵向计算&#xff09; 语法&#xff1a; select 聚合函数(字段列表) from 表名 ; 注意 : 聚合…

C++的stack和queue类(一):适配器模式、双端队列与优先级队列

目录 基本概念 stack的使用 queue的使用 适配器模式 stack.h test.cpp 双端队列-deque 仿函数 优先队列 priority_queue的使用 queue.h文件 stack.h文件 test.cpp文件 日期类的比较 商品的比较 结论 基本概念 1、stack和queue不是容器而是容器适配器&…

unable to find a medium containing a live file system解决办法!

背景&#xff1a; 用Ventoy制作U盘系统安装盘&#xff0c;只需要把ISO镜像拷进去就可以&#xff0c;可以放多少个镜像取决于U盘的大小&#xff0c;无需重复制作。Ventoy 将U盘的第一个分区默认格式化为exFAT文件系统来存放ISO文件。 但是&#xff0c;今天鲲鹏920平台安装银河…

实景三维技术在推进城市全域数字化转型的作用

4月2日&#xff0c;国家数据局发布《深化智慧城市发展推进城市全域数字化转型的指导意见&#xff08;征求意见稿&#xff09;》&#xff08;下称&#xff1a;《指导意见》&#xff09;&#xff0c;向社会公开征求意见。 《指导意见》作为推进城市数字化转型的重要文件&#xf…

蓝桥杯 交通信号 2022研究生组

问题&#xff1a; Dijstra算法变形题&#xff0c;有向边分正行和逆行方向&#xff0c;注意逆行的绿灯时间是正行的红灯时间。 这题的关键是理清从当前节点出发&#xff0c;到下一个节点是哪一时刻&#xff0c;理清这一点后&#xff0c;再跑Dijstra算法求最短路。 假设curr_t时…

美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了

写在开头 今天在牛客上看到了一个帖子&#xff0c;一个网友吐槽美团一面上来就让手撕同步器&#xff0c;没整出来&#xff0c;结果面试直接凉凉。 就此联想到一周前写的一篇关于AQS知识点解析的博文&#xff0c;当时也曾埋下伏笔说后面会根据AQS的原理实现一个自定义的同步器…

C++笔记(函数重载)

目录 引入&#xff1a; 定义&#xff1a; 易错案例&#xff1a; 引入&#xff1a; 对于实现相似功能的函数&#xff0c;在命名时&#xff0c;我们常会出现命名重复的问题。对于C语言&#xff0c;编译器遇到这种命名重复的情况&#xff0c;会进行报错。而我们的C为了更方便程…

前端开发中地图定位与距离计算的应用实践

前端开发中地图定位与距离计算的应用实践 在前端开发中&#xff0c;地图功能的应用日益广泛&#xff0c;无论是用户位置的定位、目标距离的计算&#xff0c;还是地址的解析与展示&#xff0c;地图都发挥着不可替代的作用。本文将重点介绍前端开发中实现地图定位、距离计算以及…

Docker部署前后端分离项目

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 开发环境篇 ✨特色专栏&#xff1a; M…

Unity类银河恶魔城学习记录12-7-2 p129 Craft UI - part 2源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_CraftWindow.cs using UnityEngine.UI; using TMPro; using UnityEngin…

CentOS7.9创建本地yum源操作步骤报错解决方法

1.基础信息 CentOS7.9-mini最小化安装的系统&#xff0c;在离线安装rpm时候需要大量依赖&#xff0c;需要花费大量时间去查找依赖包。受于环境限制无法接入互联网使用公开yum源&#xff0c;于是便有了搭建本机yum源的想法&#xff0c;在网上下载CentOS7.9标准版“CentOS-7-x86_…

windows 系统下 mysql 数据库的下载与安装(包括升级安装)

windows 系统下 mysql 数据库的下载与安装&#xff08;包括升级安装&#xff09; 一、mysql 介绍&#xff1a; MySQL 是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。 MySQL 是最流行的关系型数据库管理系统之一&#xf…

pyqt5 QScrollArea组件

本示例中&#xff0c;演示了QScrollArea的使用&#xff0c;以及QScrollBar的样式设定&#xff0c;在代码中使用setStyleSheet设置样式&#xff0c;记得要优先设置scrollArea&#xff0c;再设置窗口的样式&#xff0c;不然QScrollBar的样式会不起作用&#xff0c;使用QSS设置没有…

hadoop103: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

分析&#xff1a; 在启动hadoop服务的时候&#xff0c;遇到了这个问题&#xff1a; hadoop103: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password). 这个一看就是&#xff0c;密钥问题 于是ssh 主机名就行测试 需要输入密码&#xff0c;就说明这里有问…

A Note on LoRA

A Note on LoRA 摘要Additional InsightsPractical ImprovementsLooking Ahead 摘要 LoRA已成为一种首选的方法&#xff0c;用以高效地适应大型语言模型&#xff08;LLM&#xff09;&#xff0c;其简便性和有效性令人瞩目。本文档扩展了原始LoRA论文&#xff0c;提供了最初未讨…

MySQL进阶之(七)EXPLAIN 详解

七、EXPLAIN 详解 7.1 查询性能那些事7.1.1 查看系统性能参数7.1.2 统计 SQL 的查询成本7.1.3 定位执行慢的 SQL&#xff1a;慢查询日志01、开启慢查询日志参数02、关闭慢查询日志03、删除慢查询日志 7.1.4 查看 SQL 执行成本&#xff1a;SHOW PROFILE 7.2 EXPLAIN 语句输出中各…

java程序 .exe启动nginx防止重复启动,已解决

java代码生成好的.exe启动nginx服务程序 根据nginx占用端口来解决nginx服务重复启动问题&#xff08;下面代码了解代码逻辑后根据自己的业务需求修改即可&#xff09; 代码&#xff1a; package org.example;import javax.swing.*; import java.awt.*; import java.io.*; …