【C++】文件IO

目录

  • 一、C语言的输入输出
  • 二、流的概念
  • 三、operator bool
  • 四、C++文件IO流
    • ifstream和ofstream
    • ostringstream和istringstream
    • stringstream

一、C语言的输入输出

C语言中我们用到的最频繁的输入输出方式就是 scanf() 和 printf()。

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

printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。

除此之外,C语言借助了相应的缓冲区来进行输入和输出。如下图所示:
在这里插入图片描述
对输入输出缓冲区的理解:

1.可以屏蔽掉低级 I/O 的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。

2.可以使用这部分的内容实现 “行” 读取的行为,对于计算机而言是没有 “行” 这个概念,有了这部分,就可以定义“行”的概念,然后解析缓冲区的内容,返回一个“行”。

二、流的概念

“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续具有方向性 的数据( 其单位可以是 bit,byte,packet )的抽象描述。

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”。

它的特性是:有序连续、具有方向性

为了实现这种流动, C++定义了 I/O 标准类库,这些每个类都称为流/流类,用以完成某方面的功能

三、operator bool

我们之前在写OJ题的时候经常可以看到如下代码

int main()
{string s;while (cin >> s){cout << s << endl;}return 0;
}

目前我们认为cin是一个全局的类,cin>>s 的返回值其实就是cin这个全局类运算符重载>>返回的值,我们可以看一下
在这里插入图片描述
我们可以看到,重载的>>运算符返回值是一个istream的对象,不能进行while的判断,下面我们学习以下原理。

我们可以看到,内置类型可以通过隐式类型转化为自定义类型,自定义类型无法转化为内置类型

在这里插入图片描述

此时我们看到没有报错,c++一个特例,使用opertor重载,可以将自定义类型转化为内置类型

在这里插入图片描述

此时,我们可以理解上面的demo
在这里插入图片描述
在这里插入图片描述

四、C++文件IO流

我们再C++中使用的cin和cout都是继承父类,父类继承ios实现的,iostream使用菱形继承实现,同时具有istream和ostream的功能。

在这里插入图片描述
上面提到的operator bool就是基类IOS实现的,子类都没有去重写

  • cout为标准输出,将数据从内存流中输入到显示器上
  • cin为标准输入,通过键盘输入数据到程序中
  • cerr用于标准错误的输出
  • clog进行日志输出

其中需要注意的一点是,空格和回车会被当作数据之间的分隔符,所以字符串中不能有空格,回车和空格也不能通过cin读入

如果需要读入带空格的完整一行,可以使用getline函数

为什么cin和cout可以输入输出所有类型? 因为库里面已经将所有类型通过操作符重载<< 和>>实现了,达到了自动类型识别的效果
在这里插入图片描述在这里插入图片描述

之前将数据写入文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;#include<string>//IO流class Date
{
public:Date(int year,int month,int day):_year(year),_month(month),_day(day){}operator string(){string str;str += to_string(_year);str += ' ';str += to_string(_month);str += ' ';str += to_string(_day);return str;}
private:int _year;int _month;int _day;
};int main()
{Date d(2024, 2, 3);FILE* file = fopen("file.txt", "w");//fwrite(&d, sizeof(d), 1, file);//fclose(file);string str = d;fputs(str.c_str(), file);fclose(file);return 0;
}

在这里插入图片描述

我们会发现将数据写入文件比较容易,如果再将数据读出来发现比较费劲,这也是我们以前学习写入文件不足的地方,下面我们学习以下C++如何对文件进行IO

ifstream和ofstream

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;#include<string>
#include<fstream>//IO流class Date
{
public:Date() {};Date(int year,int month,int day):_year(year),_month(month),_day(day){}operator string(){string str;str += to_string(_year);str += ' ';str += to_string(_month);str += ' ';str += to_string(_day);return str;}public:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d)
{out << d._year << " " << d._month << " " << d._day;return out;
}istream& operator >>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}struct ServerInfo
{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; // 配置文件
};int main()
{ServerInfo winfo = { "192.0.0.1", 80, { 2022, 4, 10 } };// 二进制读写ConfigManager cf_bin("test.bin");cf_bin.WriteBin(winfo);ServerInfo rbinfo;cf_bin.ReadBin(rbinfo);cout << rbinfo._address << " " << rbinfo._port << " "<< rbinfo._date << endl;// 文本读写//ConfigManager cf_text("test.text");//cf_text.WriteText(winfo);//ServerInfo rtinfo;//cf_text.ReadText(rtinfo);//cout << rtinfo._address << " " << rtinfo._port << " " <<rtinfo._date << endl;return 0;
}

二进制读写
在这里插入图片描述
文本读写
在这里插入图片描述

可以看到,我们以前学的文件IO只有二进制读写比较方便,但是二进制读写可读性差,C++中使用ifstream和ofstream无论再二进制还是文本读写都非常方便。

ostringstream和istringstream

这个类可以将不同的类型转为字符串

这种操作被称为序列化和反序列化,在处理自定义类型的时候非常好用

struct Date
{
public:friend ostream& operator << (ostream& out, const Date& d);friend istream& operator >> (istream& in, Date& d);Date(int y=0, int m=0, int d=0){_year = y;_month = m;_day = d;}
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;
}void test4()
{int i = 123;double d = 44.55;ostringstream oss;//序列化oss << i;string stri = oss.str();oss.str("");//清空ossoss << d;string strd = oss.str();cout << strd<< endl;oss.str("");//清空ossDate d1(2022, 10, 11);oss << d1;string strdt = oss.str();cout << strdt << endl;istringstream iss(strdt);//反序列Date d2;iss >> d2;cout << d2 << endl;
}

在这里插入图片描述

stringstream

这个对象可以用于字符串拼接,也可以用来将其他类型转为str
在这里插入图片描述

  • stringstream实现转换,实际上是维护了一个string对象实现的

  • 我们可以使用str(“”)清空里面的string对象,设置为空字符串

  • 多次数据类型转换的时候,需要用clear()来清空,才能正确转换。不过clear()不会清空底层的string对象

  • 因为使用的是string对象,所以使用的时候不需要格式化控制,可以自动推导类型

stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit
因此下一次转换是必须调用clear()将状态重置为goodbit才可以继续转换
在这里插入图片描述
这里在第一次调用stringstream操作后,我们没有进行clear,会发现后续的double类型转换失败了

在这里插入图片描述
执行了clear之后,转换成功

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

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

相关文章

GitHub的使用操作

记得看目录哦&#xff01; 1. 创建仓库2. 下载desktop3. 把创建的库克隆到本地4. 文件拷贝到本地仓库![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7171ac6c4ca14e3b8d22717121f79c9e.png)5. 在网址后面加/compare进行比较6. 给系统添加功能 1. 创建仓库 2. 下载…

微信小程序 安卓/IOS兼容问题

一、背景 在开发微信小程序时&#xff0c;不同的手机型号会出现兼容问题&#xff0c;特此记录一下 二、安卓/IOS兼容问题总结 2.1、new Date()时间转换格式时&#xff0c;IOS不兼容 问题&#xff1a;在安卓中时间格式2024-1-31 10:10:10&#xff0c;但是在iOS中是不支持 &q…

LeetCode383. 赎金信

383. 赎金信 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1&#xff1…

工业智能网关构建智慧污水处理远程监测及管理

污水处理厂是为了处理生活污水和工业废水而建立的设施。为了监测和控制污水处理过程&#xff0c;现代污水处理厂采用了智能工业网关物联网技术。智慧污水系统能够通过工业网关远程监测厂内各个环节的运行情况&#xff0c;提高处理效率和管理水平。 智能工业网关能够将不同设备…

Vue3学习记录(二)--- 组合式API之计算属性和侦听器

一、计算属性 1、简介 ​ 计算属性computed()&#xff0c;用于根据依赖的响应式变量的变化&#xff0c;进行自动的计算&#xff0c;并返回计算后的结果。当依赖的响应式变量发生变化时&#xff0c;computed()会自动进行重新计算&#xff0c;并返回最新的计算结果。如果依赖的…

9 个成功的会员网站案例

对于许多数字创作者来说&#xff0c;会员网站可以改变游戏规则。 当您建立一个会员网站时&#xff0c;您不仅会提高收入。也可以根据您的主题或想法创建有意义的业务。围绕这种想法将人们联系起来。 如果您正在考虑创建一个会员网站 或想要修改您的会员网站&#xff0c;我们将…

【Chrono Engine学习中总结】1-安装配置与程序运行

本文仅用于个人安装记录。 官方安装教程 https://api.projectchrono.org/8.0.0/tutorial_install_chrono.html Windows下安装 windows下安装就按照教程好了。采用cmake-gui进行配置&#xff0c;建议首次安装只安装核心模块。然后依此configure下irrlicht&#xff0c;sensor…

vue3前端开发,element-plus前端框架探秘:scope对象

vue3前端开发&#xff0c;element-plus前端框架探秘:scope对象&#xff01;我们经常需要对当前行的数据进行操作&#xff0c;比如增加&#xff0c;删除&#xff0c;编辑等&#xff0c;为此我们需要传递当前行所对应的唯一主键,通常情况下&#xff0c;当前行对应的业务主键是id属…

Camille-学习笔记-web基础知识

web基础1.系统架构 B/S :Browser/Server 网站 界面层&#xff08;UI&#xff09; 业务逻辑层&#xff08;业务&#xff09; 数据访问层&#xff08;数据库&#xff09; 静态网页&#xff1a;和服务器没有数据交互 动态网页&#xff1a;网页数据可以和服务器进行数据交互 URL…

C++学习Day01之C++对C语言增强和扩展

目录 一、程序及输出1.1 全局变量检测增强1.2 函数检测增强1.3 类型转换检测增强1.4 struct增强1.5 bool类型扩展1.6 三目运算符增强1.7 const增强1.7.1 全局Const对比1.7.2 局部Const对比1.7.3 Const变量初始化数组1.7.3 Const修饰变量的链接性 二、分析总结 一、程序及输出 …

React + react-device-detect 实现设备特定的渲染

当构建响应式网页应用时&#xff0c;了解用户正在使用的设备类型&#xff08;如手机、平板或桌面&#xff09;可以帮助我们提供更优化的用户体验。本文将介绍如何在 React 项目中使用 react-device-detect 库来检测设备类型&#xff0c;并根据不同的设备显示不同的组件或样式。…

由反射引出的Java动态代理与静态代理

写在开头 在《深入剖析Java中的反射&#xff0c;由浅入深&#xff0c;层层剥离&#xff01;》这篇文章中我们讲反射时&#xff0c;曾提到过Java的动态代理中使用了反射技术&#xff0c;那么好&#xff0c;今天我们要就着反射的索引&#xff0c;来学习一下Java中的代理&#xf…