Cpp::IO流(37)
文章目录
- 前言
- 一、C语言的输入与输出
- 二、什么是流?
- 三、C++ IO流
- C++标准IO流
- C++文件IO流
- 以写方式打开文件
- 以读方式打开文件
- 四、stringstream的简单介绍
- 总结
前言
芜湖,要结束喽!
一、C语言的输入与输出
C语言中我们用到的最频繁的输入输出方式就是 scanf () 与 printf() 。
scanf( ): 从标准输入设备(键盘)读取数据,并将值存放在变量中。
printf( ): 将指定的文字 / 字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来进行输入与输出。
输入输出缓冲区的意义:
- 可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序
- 可以使用这部分的内容实现 “行” 读取的行为,对于计算机而言是没有 “行” 这个概念,有了这部分,就可以定义 “行” 的概念,然后解析缓冲区的内容,返回一个 “行”
二、什么是流?
其实,“流” 的概念我们之前就有过了解,现在我们再来回顾一下
“流” 即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据( 其单位可以是bit,byte,packet )的抽象描述
而 C++流 是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为 “流”
有序连续、具有方向性
为了实现这种流动,C++定义了 I/O标准类库 ,这些每个类都称为流 / 流类,用以完成某方面的功能
三、C++ IO流
C++系统 实现了一个庞大的类库,其中 ios 为基类,其他类都是直接或间接派生自 ios类
C++标准IO流
C++标准库提供了4个全局流对象 cin、cout、cerr、clog,使用 cout 进行标准输出,即数据从内存流向控制台(显示器)。使用 cin 进行标准输入即数据通过键盘输入到程序中,同时 C++标准库 还提供了 cerr 用来进行标准错误的输出,以及 clog 进行日志的输出,从上图可以看出,cout、cerr、clog是 ostream类 的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同
- cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。
- 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对应位置位(置1),程序继续。
- 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入。
- cin 和 cout 可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了
int main()
{// 标准输出流cout << "xxxx" << endl;// 错误的标准输出流cerr << "yyyy" << endl;// 用于日志记录的标准输出流clog << "zzzz" << endl;int x = 0;// 检查流的状态是否良好cout << cin.good() << endl;// 检查是否设置了 eofbitcout << cin.eof() << endl;// 检查是否设置了failbit或badbitcout << cin.fail() << endl;// 检查是否设置了badbit cout << cin.bad() << endl << endl;cin >> x;cout << x << endl;cout << cin.good() << endl;cout << cin.eof() << endl;cout << cin.fail() << endl;cout << cin.bad() << endl << endl;return 0;
}
-
对于自定义类型,如果要支持 cin 和 cout 的标准输入输出,需要对 << 和 >> 进行重载
-
istream类型对象转换为逻辑条件判断值
istream& operator>> (int& val);
explicit operator bool() const;
实际上我们看到使用 while( cin>>i ) 去流中提取对象数据时,调用的是 operator>> ,返回值是 istream类型 的对象,那么这里可以做逻辑条件值,源自于 istream 的对象又调用了 operator bool ,operator bool 调用时如果接收流失败,或者有结束标志,则返回 false
日期类
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(){// 这里是随意写的,假设输入_year为0,则结束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& operator<<(ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}// C++ IO流,使用 面向对象 + 运算符重载 的方式
// 能更好的兼容自定义类型,流插入和流提取
int 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;}return 0;
}
文件读写相关类
struct ServerInfo
{// string _address;char _address[32];int _port;Date _date;
};struct ConfigManager
{
public:ConfigManager(const char* filename):_filename(filename){}// 二进制// 内存中怎么存,囫囵吞枣,怎么写出去void WriteBin(const ServerInfo& info){ofstream ofs(_filename, ios_base::out | ios_base::binary);ofs.write((const char*)&info, sizeof(info));}void ReadBin(ServerInfo& info){ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs.read((char*)&info, sizeof(info));}void WriteText(const ServerInfo& info){ofstream ofs(_filename);ofs << info._address << " " << info._port << " " << info._date;}void ReadText(ServerInfo& info){ifstream ifs(_filename);ifs >> info._address >> info._port >> info._date;}private:string _filename; // 配置文件
};
二进制方式写文件
// 二进制方式读写文件// (当成员是 string 时会有错误,因为 string 读取的是地址,而不是实际的字符串内容)
int main()
{ServerInfo winfo = { "192.0.0.111", 80, { 2022, 4, 10 } };// 写文件ConfigManager cf_bin("test.bin");cf_bin.WriteBin(winfo);return 0;
}
以上说的成员使用 string 时会发生错误,原因在于:
二进制读写是直接将内存中的数据原样写入文件或从文件中读取到内存。对于基本数据类型(如 int、char 等)和固定大小的数组,这种方式是可行的,因为它们在内存中是连续存储的,并且大小是固定的。例如,int 类型通常占 4 个字节,char[32] 数组占 32 个字节,二进制读写可以准确地处理这些数据
当使用二进制方式将包含 std::string 成员的结构体写入文件时,实际写入的是 std::string 对象内部的指针和长度等信息,而不是字符串的实际内容
写入文件时:假设 std::string 对象内部有一个指针 data 指向动态分配的字符串数据,二进制写入操作会将这个指针的值(即内存地址)写入文件,而不是指针所指向的实际字符串内容。
从文件读取时:读取操作会将之前写入的指针值读回到内存中。但这个指针指向的是写入时的内存地址,在读取时这个地址可能已经无效(例如,该内存可能已经被释放或被其他数据覆盖),或者指向的内容已经改变。因此,读取到的 std::string 对象无法正确访问实际的字符串内容,从而导致错误
二进制方式读文件
int main()
{ConfigManager cf_bin("test.bin");ServerInfo rbinfo;// 读文件cf_bin.ReadBin(rbinfo);cout << rbinfo._ip << " " << rbinfo._port << " " << rbinfo._date << endl;return 0;
}
文本方式写文件
int main()
{ServerInfo winfo = { "192.0.0.1xxxxxxxxxxxx", 80, { 2022, 4, 10 } };// 文本写ConfigManager cf_text("test.text");cf_text.WriteText(winfo);return 0;
}
文本方式读文件
int main()
{ConfigManager cf_text("test.text");ServerInfo rtinfo;// 文本读cf_text.ReadText(rtinfo);cout << rtinfo._ip << " " << rtinfo._port << " " << rtinfo._date << endl;return 0;
}
C++文件IO流
C++根据文件内容的数据格式分为 二进制文件 和 文本文件 。采用文件流对象操作文件的一般步骤如下:
- 定义一个文件流对象
ifstream ifile(只输入用)
ofstream ofile(只输出用)
fstream iofile(既输入又输出用) - 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
- 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
- 关闭文件
以写方式打开文件
#include <fstream>// 写文件 ofstream
int main()
{// in:读 out:写 app:追加 binary:二进制// ofstream ofs("test.txt", ofstream::out);ofstream ofs("test.txt", ofstream::out | ofstream::app);// 写进文件中ofs << "yyyyyyyyy" << endl;return 0;
}
以读方式打开文件
int main()
{//ifstream ofs("test.cpp");ifstream ofs("C:\\Users\\lhq\\Desktop\\C++中程序内存区域划分.png", ios_base::in | ios_base::binary);int n = 0;while (!ofs.eof()){char ch = ofs.get();//cout << ch;++n;}cout << n << endl;return 0;
}
四、stringstream的简单介绍
在C语言中,如果想要将一个 整形变量 的数据转化为 字符串格式 ,如何去做?
- 使用 itoa( ) 函数
- 使用 sprintf( ) 函数
int main()
{int n = 123456789;char s1[32];_itoa(n, s1, 10);char s2[32];sprintf(s2, "%d", n);return 0;
}
但是两个函数在转化时,都得需要先给出保存结果的空间,那空间要给多大呢,就不太好界定
所以我们就要来学习 stringstream类 对象,它的作用如下:
- 将数值类型数据格式化为字符串
#include<sstream>int main()
{int a = 12345678;string sa;// 将一个整形变量转化为字符串,存储到 string 类对象中stringstream s;s << a;s >> sa;cout << sa << endl;// clear()// 注意多次转换时,必须使用 clear 将上次转换状态清空掉// stringstreams 在转换结尾时(即最后一个转换后),会将其内部状态设置为 badbit// 因此下一次转换是必须调用 clear() 将状态重置为 goodbit 才可以转换// 但是 clear() 不会将 stringstreams 底层字符串清空掉// s.str("");// 将stringstream底层管理string对象设置成"",// 否则多次转换时,会将结果全部累积在底层string对象中s.str("");s.clear();// 清空s, 不清空会转化失败double d = 12.34;// 将一个浮点数变量转化为字符串,存储到string类对象中s << d;s >> sa;cout << sa << endl;string sValue;sValue = s.str();// str()方法:返回stringsteam中管理的string类型cout << sValue << endl;return 0;
}
- 字符串拼接
int main()
{stringstream sstream;// 将多个字符串放入 sstream 中sstream << "first" << " " << "string,";sstream << " second string";cout << "strResult is: " << sstream.str() << endl;// 清空 sstreamsstream.str("");sstream << "third string";cout << "After clear, strResult is: " << sstream.str() << endl;return 0;
}
总结
应该 C++ 的学习之路到此就结束了,我回看了一下这个专栏,反向迭代器、布隆过滤器、并发库等内容还没有讲解,(其实,我目前也没搞很懂) ,之后可能会还有补充,但肯定不是最近的事情~
嗟乎!C++ 之盛,其兴也勃焉;内存之危,其亡也忽焉。夫编程战国之时,Java 虚拟机坐大,Python 弱冠弄巧,C# 借势微软,然终为 C++ 囊括四海,并吞八荒。当是时也,指针为矢,模板为刃,RAII 守疆,const 镇国,宰制六合,何其壮也!
相关文章:

Cpp::IO流(37)
文章目录 前言一、C语言的输入与输出二、什么是流?三、C IO流C标准IO流C文件IO流以写方式打开文件以读方式打开文件 四、stringstream的简单介绍总结 前言 芜湖,要结束喽! 一、C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是 …...

基于OpenCV实现的答题卡自动判卷系统
一、图像预处理 🌄 二、查找答题卡轮廓 📏 三、透视变换 🔄 四、判卷与评分 🎯 五、主函数 六、完整代码+测试图像集 总结 🌟 在这篇博客中,我将分享如何使用Python结合OpenCV库开发一个答题卡自动判卷系统。这个系统能够自动从扫描的答题卡中提取信…...

如何将电脑桌面默认的C盘设置到D盘?详细操作步骤!
将电脑桌面默认的C盘设置到D盘的详细操作步骤! 本博文介绍如何将电脑桌面(默认为C盘)设置在D盘下。 首先,在D盘建立文件夹Desktop,完整的路径为D:\Desktop。winR,输入Regedit命令。(或者单击【…...

二十三种设计模式-享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享相同对象来减少内存使用,尤其适合在大量重复对象的情况下。 核心概念 享元模式的核心思想是将对象的**可共享部分(内部状态)提取出来进行共…...

算法【有依赖的背包】
有依赖的背包是指多个物品变成一个复合物品(互斥),每件复合物品不要和怎么要多种可能性展开。时间复杂度O(物品个数 * 背包容量),额外空间复杂度O(背包容量)。 下面通过题目加深理解。 题目一 测试链接:[NOIP2006 提…...

A7. Jenkins Pipeline自动化构建过程,可灵活配置多项目、多模块服务实战
服务容器化构建的环境配置构建前需要解决什么下面我们带着问题分析构建的过程:1. 如何解决jenkins执行环境与shell脚本执行环境不一致问题?2. 构建之前动态修改项目的环境变量3. 在通过容器打包时避免不了会产生比较多的不可用的镜像资源,这些资源要是不及时删除掉时会导致服…...

飞牛NAS新增虚拟机功能,如果使用虚拟机网卡直通安装ikuai软路由(如何解决OVS网桥绑定失败以及打开ovs后无法访问飞牛nas等问题)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 飞牛NAS虚拟机安装爱快教程 📒🛠️ 前期准备🌐 网络要求💾 下载爱快镜像🚀 开始安装💻 开启IOMMU直通🌐 配置网络🚨 解决OVS网桥绑定失败以及打开ovs后无法访问飞牛nas等问题➕ 创建虚拟机🎯 安装ikuai💻 进…...

蓝桥杯例题四
每个人都有无限潜能,只要你敢于去追求,你就能超越自己,实现梦想。人生的道路上会有困难和挑战,但这些都是成长的机会。不要被过去的失败所束缚,要相信自己的能力,坚持不懈地努力奋斗。成功需要付出汗水和努…...

八股——Java基础(四)
目录 一、泛型 1. Java中的泛型是什么 ? 2. 使用泛型的好处是什么? 3. Java泛型的原理是什么 ? 什么是类型擦除 ? 4.什么是泛型中的限定通配符和非限定通配符 ? 5. List和List 之间有什么区别 ? 6. 可以把List传递给一个接受List参数的方法吗? 7. Arra…...

CVE-2023-38831 漏洞复现:win10 压缩包挂马攻击剖析
目录 前言 漏洞介绍 漏洞原理 产生条件 影响范围 防御措施 复现步骤 环境准备 具体操作 前言 在网络安全这片没有硝烟的战场上,新型漏洞如同隐匿的暗箭,时刻威胁着我们的数字生活。其中,CVE - 2023 - 38831 这个关联 Win10 压缩包挂…...

【自然语言处理(NLP)】深度循环神经网络(Deep Recurrent Neural Network,DRNN)原理和实现
文章目录 介绍深度循环神经网络(DRNN)原理和实现结构特点工作原理符号含义公式含义 应用领域优势与挑战DRNN 代码实现 个人主页:道友老李 欢迎加入社区:道友老李的学习社区 介绍 **自然语言处理(Natural Language Pr…...

Linux 命令之技巧(Tips for Linux Commands)
Linux 命令之技巧 简介 Linux 是一种免费使用和自由传播的类Unix操作系统,其内核由林纳斯本纳第克特托瓦兹(Linus Benedict Torvalds)于1991年10月5日首次发布。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户…...

【文星索引】搜索引擎项目测试报告
目录 一、项目背景二、 项目功能2.1 数据收集与索引2.2 API搜索功能2.3 用户体验与界面设计2.4 性能优化与维护 三、测试报告3.1 功能测试3.2 界面测试3.3 性能测试3.4 兼容性测试3.5 自动化测试 四、测试总结4.1 功能测试方面4.2 性能测试方面4.3 用户界面测试方面 一、项目背…...

低代码系统-产品架构案例介绍、轻流(九)
轻流低代码产品定位为零代码产品,试图通过搭建来降低企业成本,提升业务上线效率。 依旧是从下至上,从左至右的顺序 名词概述运维层底层系统运维层,例如上线、部署等基础服务体系内置的系统能力,发消息、组织和权限是必…...

二叉树(补充)
二叉树 1.二叉树的基本特性2.堆2.1.堆的基本概念2.2.堆的实现2.2.1.基本结构2.2.2.堆的初始化 2.2.3.堆的销毁2.2.4.堆的插入2.2.5.取出堆顶的数据2.2.6.堆的删除2.2.7.堆的判空2.2.8.堆的数据个数2.2.9.交换2.2.10.打印堆数据2.2.11.堆的创建2.2.12.堆排序 1.二叉树的基本特性…...

(DM)达梦数据库基本操作(持续更新)
1、连接达梦数据库 ./disql 用户明/"密码"IP端口或者域名 2、进入某个模式(数据库,因达梦数据库没有库的概念,只有模式,可以将模式等同于库) set schema 库名; 3、查表结构; SELECT COLUMN_NAM…...

CRM 微服务
文章目录 项目地址一、项目地址 教程作者:教程地址:代码仓库地址:所用到的框架和插件:dbt airflow一、 用户与认证服务 主要功能: 用户注册、登录、注销。 认证(OAuth、JWT 等)。 权限和角色管理(RBAC/ABAC)。 单点登录(SSO)。 技术亮点: 集成第三方身份认证(如 …...

AI软件外包需要注意什么 外包开发AI软件的关键因素是什么 如何选择AI外包开发语言
1. 定义目标与需求 首先,要明确你希望AI智能体做什么。是自动化任务、数据分析、自然语言处理,还是其他功能?明确目标可以帮助你选择合适的技术和方法。 2. 选择开发平台与工具 开发AI智能体的软件时,你需要选择适合的编程语言、…...

DBSyncer开源数据同步中间件
一、简介 DBSyncer(英[dbsɪŋkɜː(r)],美[dbsɪŋkɜː(r) 简称dbs)是一款开源的数据同步中间件,提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景。支持上传插件自定义同步转换业务,提供监控全量…...

< OS 有关 > 阿里云 几个小时前 使用密钥替换 SSH 密码认证后, 发现主机正在被“攻击” 分析与应对
信息来源: 文件:/var/log/auth.log 因为在 sshd_config 配置文件中,已经定义 LogLevel INFO 部分内容: 2025-01-27T18:18:55.68272708:00 jpn sshd[15891]: Received disconnect from 45.194.37.171 port 58954:11: Bye Bye […...

react-bn-面试
1.主要内容 工作台待办 实现思路: 1,待办list由后端返回,固定需要的字段有id(查详细)、type(本条待办的类型),还可能需要时间,状态等 2,一个集中处理待办中转路由页,所有待办都跳转到这个页面…...

1. Java-MarkDown文件创建-工具类
Java-MarkDown文件创建-工具类 1. 思路 根据markdown语法,拼装markdown文本内容 2. 工具类 import java.util.Arrays; import java.util.List;/*** Markdown生成工具类* Author: 20004855* Date: 2021/1/15 16:00*/ public class MarkdownGenerator {private Str…...

全连接神经网络(前馈神经网络)
一、全连接神经网络介绍 在多层神经网络中, 第 N 层的每个神经元都分别与第 N-1 层的神经元相互连接。 1、神经元 这个神经元接收的输入信号为向量 , 向量为输入向量的组合权重, 为偏置项, 是一个标量。 神经元的作用是对输入向…...

【llm对话系统】什么是 LLM?大语言模型新手入门指南
什么是 LLM?大语言模型新手入门指南 大家好!欢迎来到 LLM 的奇妙世界!如果你对人工智能 (AI) 的最新进展,特别是那些能像人类一样阅读、写作甚至进行对话的 AI 感兴趣,那么你来对地方了。这篇文章将带你认识 LLM 的基…...

【Linux】互斥锁、基于阻塞队列、环形队列的生产消费模型、单例线程池
⭐️个人主页:小羊 ⭐️所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 1、互斥锁2、生产消费模型2.1 阻塞队列2.2 环形队列 3、单例线程池4、线程安全和重入问题 1、互斥锁 临界资源:多线程…...

【学术会议征稿】第五届能源、电力与先进热力系统学术会议(EPATS 2025)
能源、电力与先进热力系统设计是指结合物理理论、工程技术和计算机模拟,对能源转换、利用和传输过程进行设计的学科领域。它涵盖了从能源的生产到最终的利用整个流程,旨在提高能源利用效率,减少能源消耗和环境污染。 重要信息 官网…...

ES6 类语法:JavaScript 的现代化面向对象编程
Hi,我是布兰妮甜 !ECMAScript 2015,通常被称为 ES6 或 ES2015,是 JavaScript 语言的一次重大更新。它引入了许多新特性,其中最引人注目的就是类(class)语法。尽管 JavaScript 一直以来都支持基于…...

Sprintboot原理
配置优先级 Springboot中支持的三种配置文件: application.propertiesapplication.ymlapplication.yaml java系统属性:-Dxxxxxx 命令行参数:-xxxxxx 优先级:命令行参数>java系统属性>application.properties>applicat…...

OpenHarmony 5.0.2 Release来了!
版本概述 OpenHarmony 5.0.2 Release版本对标准系统的能力进行持续完善,以快速迭代的方式推出API 14,相比5.0.1 Release版本,重点做出了如下特性新增或增强: 进一步增强ArkUI、图形图像的能力,提供更多组件的高级属性…...

Qt 控件与布局管理
1. Qt 控件的父子继承关系 在 Qt 中,继承自 QWidget 的类,通常会在构造函数中接收一个 parent 参数。 这个参数用于指定当前空间的父控件,从而建立控件间的父子关系。 当一个控件被设置为另一控件的子控件时,它会自动成为该父控…...