C++ IO流

news2024/11/25 20:24:46

文章目录

  • C语言的输入与输出
  • 流是什么?
  • C++IO流
    • C++标准IO流
    • C++文件流
  • stringstream的简单介绍

C语言的输入与输出

在C语言中,我们使用最频繁的输入输出方式为: scanf 和 printf.

  1. scanf : 从输入设备(键盘)读取数据,并将值存放在变量中.
  2. printf: 将指定的文字/字符串输出到标准输出设备(屏幕).
    在这里插入图片描述

流是什么?

  • "流"即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据的抽象概述.
  • C++流是指信息从输入设备(如键盘)向内存输入和信息从内存向输出设备输出的过程,这种输入输出的过程被形象的比喻为"流".

流的特征为: 有序连续,具有方向性.

C++IO流

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或者间接继承自ios类.
在这里插入图片描述

C++标准IO流

C++标准库提供了4个全局流对象(cin、cout、cerr、clog).

  • 使用cout进行标准输出,即数据从内存流向控制台(显示器).
  • 使用cin进行标准输入,即数据通过键盘输入到程序中.
  • 使用cerr进行标准错误的输出.
  • 使用clog进行日志的输出.

注意:

  1. cin为缓冲流,键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中提取,如果一次性输入过多,则多余的数据会保存在缓冲区中以供之后提取,如果输错了,必须在回车之前进行修改,如果回车键按下就无法修改了,只有将输入缓冲区的数据读取完之后的数据才要求输入新的数据.
int main()
{
	int a , b;
	cin >> a; //向放缓冲区中输入 1 , 2
	cout << a << endl;
	cin >> b; //直接从输入缓冲区提取2,不用认为输入
	cout << b << endl;
	return 0;
}

2.输入的数据类型必须与要提取的数据类型一致.

3.回车和空格都可以作为数据之间的分隔符,所以多个数据可以在一行输入,也可以分行输入.但是如果是字符型和字符串,则空格无法用cin输入,字符串中也不能有空格.回车键也无法读入.


int main()
{
	string s;
	cin >> s;          //输入:"hello yzh"
	cout << s << endl; //输出:"hello"
	return 0;
}

对于含有空格的字符串,我们可以尝试采用getline函数进行读取,因为getline函数只有遇到’\n’才会停止读取.

int main()
{
	string s;
	
	getline(cin, s); //输入: "hello yzh";

	cout << s << endl; //输出:"hello yzh

	return 0;
}

4:对于内置类型,cin和cout可以直接输入和输出相关数据,原因:标准库已经将所有内置类型的输入和输出全部重载了,

流插入: >>
在这里插入图片描述
流提取: <<
在这里插入图片描述
5:对于自定义类型,如果要支持cin和cout的标准输入输出,需要对<<和>>进行重载.

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)
	{}
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 de;

	cin >> de; //2023 7 6

	cout << de; //2023 7 6

	return 0;
}

6: 在线OJ中的输入和输出.

  • 对于IO类型的算法,一般需要循环输入.
  • 输出:严格按照题目的要求进行,不能多一个空格或者少一个空格.
  • 连续输入时,VS系列编译器在输入ctrl+Z时结束.

例如: C语言中的cin和C++中的scanf默认都是用空格和换行分割的.

输入格式:2023 07 06

int main()
{
	int year, month, day;

	cin >> year >> month >> day; // 2023 07 06

	scanf("%d%d%d", &year, &month, &day); // 2023 07 06

	return 0;
}

输入格式:20230706
要达到输入格式C语言可以利用sancf中规定年为4个位置,月为2个位置,日为2个位置.

int main()
{
	int year, month, day;

	scanf("%4d%2d%2d", &year, &month, &day); //输入格式:20230706

	return 0;
}

C++只能通过stoi函数将数字字符串按照年,月,日的格式进行分割,然后将数字字符串格式转换为整数.

int main()
{
	int 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));

	cout << year << "年" << month << "月" << day<<"日";
}

并且,C++中还可以通过while循环支持多行测试用例,当然,我们可以使用ctrl+z+换行给一个流读取结束的标志.

int main()
{
	int year, month, day;

	string str;
	
	while (cin >> str)
	{
		year = stoi(str.substr(0, 4));

		month = stoi(str.substr(4, 2));

		day = stoi(str.substr(6, 2));

		cout << year << "年" << month << "月" << day<<"日";
	}
	return 0;
}

C++文件流

二进制读写; 在内存中如何存储,就如何写到磁盘文件上.

  • 优点: 读写快.
  • 缺点: 写入打文件,但是文件内容看不见.

文本读写: 序列化成字符串写出来,读回来也是字符串,

  • 可以看见具体内容.
  • 存在一个转换过程,读写速度慢.

C++根据文件内容的数据格式分为二进制文件和文本文件。采用文件流对象操作文件的一般步骤.

  1. 定义一个文件流对象
  • istream ifile(只输入用)
  • ofstream ofile(只输出用)
  • fstream iofile(既输入又输出用)

2.使用文件流对象的成员函数打开一个磁盘文件,使的文件流对象和磁盘文件之间建立联系.( 输入或者输出).

3.利用提取和插入运算符对文件进行读写操作,或者使用成员函数进行读写.

以下为C++IO流文本读,写以及二进制读写.

struct ServerInfo
{
	//char _address[32];  //用于二进制读写,必须采用字符数组,不能采用string类.

	string _address;  //用于文本读写,可以采用string类.

	int _port;
	
};
class ConfigManager
{
public:
	ConfigManager(const char* filename = "sever.config")
		:_filename(filename)
	{}

	//二进制写:将数据写道文件里面.
	void WriteBin(ServerInfo& info)
	{
		ofstream ofs(_filename, ios_base::out | ios_base::binary); //以二进制覆盖写的方式打开文件.
		ofs.write((const char*)&info, sizeof(info));   //将目标大小的数据写入.
	}

	//二进制读,将文件里面的数据读取到内存中.
	void ReadBin(const ServerInfo& info)
	{
		ifstream ifs(_filename, ios_base::in | ios_base::binary);//以二进制读的方式打开文件.
		ifs.read((char*)&info, sizeof(info));  //将目标大小的数据读取.
	}


	//文本读(输入到内存中)
	void ReadText1(ServerInfo& info)
	{
		ifstream ifs(_filename, ios_base::in);

		ifs >> info._address >> info._port;
	}

	//文本写(输出到文件中)
	void WriteText1(ServerInfo& info)
	{
		ofstream ofs(_filename, ios_base::out);

		ofs << info._address << endl;

		ofs << info._port << endl;

	}

private:
	string _filename;  //配置文件.

};

测试案例如下:

int main() {
	//写入数据(二进制)
	ServerInfo winfo = { "127.0.0.1",888 };

	ConfigManager cm;

	cm.WriteBin(winfo);

	//读取数据(二进制)
	/*ServerInfo rinfo;

	ConfigManager cm;

	cm.ReadBin(rinfo);

	cout << rinfo._address << endl;   //打印

	cout << rinfo._port << endl;*/

	//文本写.
	//ServerInfo winfo = { "127.0.0.1",888};

	//ConfigManager cm;

	//cm.WriteText1(winfo);


	//文本读.
	//ServerInfo rinfo;

	//ConfigManager cm;

	//cm.ReadText1(rinfo);

	//cout << rinfo._address << endl;

	//cout << rinfo._port << endl;


	return 0;
}

注意:

  • 使用二进制读写时,如果目标数据由string类,vector类存储,那么写入到文件的时候并不是将数组的内容写入,而是将string字符串数组的地址,capacity等写入.该地址也对应着"写入文件"时这一进程.可是,当我们将从文件读取(输入)到内存中时,会将上一进程中写入的地址读取,可是,在新的进程中,该地址是无效的,对应着野指针.
  • 所以二进制读写不适合深浅拷贝的类,一般采用字符数组存储数据.

二进制读,写的自己实现

对文本读来说,我们可以调用ifstream类对象中的成员函数读取文本数据,这一过程也成为输入,步骤如下:

  • 创建ifs对象并二进制以读的形式当打开文件.
  • 创建输入缓冲区
  • 依次调用getline函数对文本数据行读取到缓冲区中.
  • 依次将缓冲区的数据放入对应的变量中.
	void ReadText( ServerInfo& info)
	{
		ifstream ifs(_filename, ios_base::in | ios_base::binary);

		char buff[128];

		ifs.getline(buff, 128); //1

		info._address = buff; //将读取的数据放在对应的变量中.

		ifs.getline(buff, 128); //2

		info._port = stoi(buff);//将读取的数据转回整型变量中.

	}

对于文本写来说,我们也可ofstream类对象中的成员函数将数据写入文件中,这一过程也成为输出.步骤如下:

  • 创建ofs对象并二进制以写的形式当打开文件.
  • 依次将目标数据写入到文件中
	void WriteText(const ServerInfo& info)
	{
		ofstream ofs(_filename, ios_base::out | ios_base::binary);

		ofs.write(info._address.c_str(), info._address.size());   //1

		ofs.put('\n'); //'n'分割数据,读取时方便分辨.

		const string str = to_string(info._port);//2

		ofs.write(str.c_str(), str.size());
	}

利用istream类对象中的get()函数读取Test.cpp文件中的数据(输入),然后再利用cout将打印出来.

int main()
{
	ifstream ifs("Test.cpp");

	char ch = ifs.get();

	while (ifs)
	{
		cout << ch;
		ch = ifs.get();
	}
	return 0;
}

stringstream的简单介绍

在C++中,我们可以使用stringstream来将整型变量的数据达转换为字符串形式.主要有两种使用方式:
1.将数值数据格式转化为字符串.

int main()
{
	//方法一:
	int a = 10;
	string sa;
	stringstream s;
	s << a; //将int类型的a放入输入流
	s >> sa; //从s中抽取前面插入的int类型的值,赋值给string类型
	cout << sa << endl;

	//方法二:
	s.str(""); //将stringstream底层管理的string对象设置为""。
	s.clear(); //将上次转换状态清空掉
	//进行下一次转换
	double b = 3.14;
	s << b;
	sa = s.str(); //获取stringstream中管理的string类型(方式二)
	cout << sa << endl;
	return 0;
}

2.字符串拼接.

int main()
{
	//方法一:
	string rets;
	stringstream s;
	s << "hello" << "yzh"; //将多个字符串放入stringstream中
	s >> rets; 
	cout << rets << endl;

	//方法二:
	s.str(""); //将stringstream底层管理的string对象设置为空字符串
	s.clear(); //将上次转换状态改变.
	s << "welcome" << " " << "to" << " " << "C++"; //将多个字符串放入stringstream中
	rets = s.str(); 
	cout << rets << endl;
	return 0;
}

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)
	{}
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;
}
struct ChatInfo
{
	string _name;
	int _id;
	Date _date;
	string _msg;
};
int main()
{
	// 结构信息序列化为字符串
	ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧"
	};
	stringstream oss;
	oss << winfo._name << " " << winfo._id << " " << winfo._date << " "
		<< winfo._msg;
	string str = oss.str();
	cout << str << endl << endl;
	// 我们通过网络这个字符串发送给对象,实际开发中,信息相对更复杂,
	   // 一般会选用Json、xml等方式进行更好的支持
	// 字符串解析成结构信息
	ChatInfo rInfo;
	stringstream iss(str);
	iss >> rInfo._name >> rInfo._id >> rInfo._date >> rInfo._msg;
	cout << "-------------------------------------------------------"
		<< endl;
	cout << "姓名:" << rInfo._name << "(" << rInfo._id << ") ";
	cout << rInfo._date << endl;
	cout << rInfo._name << ":>" << rInfo._msg << endl;
	cout << "-------------------------------------------------------"
		<< endl;
	return 0;
}

注意:

  • 序列化与反序列化也可以使用ostringstream和istringstream操作,效果与用法stringstream相同.
  • stringstream实际是在底层维护了一个string类型的对象用来保存结果。
  • stringstream在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit,因此在下一次转换前必须调用clear将状态重置为goodbit才可以转换,但clear不会将stringstream底层的string对象清空。
  • 所以,我们可以使用s.str(“”)的方式将stringstream底层的string对象设置为空字符串,否则多次转换时,会将结果全部累积在底层string对象中。
  • 使用stringstream转换后可以使用 >> 运算符 也可以 使用使用s.str()将让stringstream返回其底层的string对象。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库约束与表的关系(数据库系列4)

目录 前言&#xff1a; 1.数据库的约束 1.1约束类型 1.1.1 not null 1.1.2 unique 唯一约束 1.1.3 default 默认值约束 1.1.4 primary key 主键约束 1.1.5 foreign key 外键约束 2.表的关系 2.1 一对一 2.2 一对多 2.3 多对一 3.新增 4.聚合查询 4.1聚合函数 4.…

Pinecone - 向量数据库

文章目录 关于 PineconeRoadMapSemantic SearchChatbots购买查看 API Key创建索引代码调用安装库 pinecone-client查看已经创建的索引创建索引插入数据获取索引统计分析信息查询索引,获取相似向量删除索引关于 Pinecone 官网 : https://www.pinecone.i

利用layui构建OA系统基本操作

一.编写方法&#xff08;增加&#xff0c;删除&#xff0c;修改&#xff0c;查询&#xff09; 通过继承BaseDao来实现通用&#xff0c;从而减少代码量&#xff0c;提高小路 1.增加 public int add(User user) throws Exception {String sql "insert into t_oa_user(name…

Windows7中使用SRS集成音视频一对一通话

SRS早就具备了SFU的能力&#xff0c;比如一对一通话、多人通话、直播连麦等等。在沟通中&#xff0c;一对一是常用而且典型的场景&#xff0c; 让我们一起来看看如何用SRS做直播和RTC一体化的一对一通话。 一、启动windows7-docker 二、拉取SRS镜像 执行命令:docker pull oss…

修改jar包中的文件内容

文章目录 导引查找是否存在需要修改的文件vim命令修改配置文件jar命令替换jar包中的文件(也可新增)解压jar包&#xff0c;修改后重新打包jar修改clas文件jar命令参数 导引 首先问问为什么要直接修改jar包中的文件&#xff0c;而不是重新打包&#xff0c;在非必要的情况下&…

【动手学深度学习】pytorch-参数管理

pytorch-参数管理 概述 我们的目标是找到使损失函数最小化的模型参数值。 经过训练后&#xff0c;我们将需要使用这些参数来做出未来的预测。 此外&#xff0c;有时我们希望提取参数&#xff0c;以便在其他环境中复用它们&#xff0c; 将模型保存下来&#xff0c;以便它可以在…

python数据挖掘基础环境安装和使用

文章目录 一&#xff0e;安装python环境二、库的安装2.1 使用pip命令安装virtualenvv扩展&#xff1a;cmd无法使用pip&#xff0c;报错&#xff1a;Fatal error in launcher: Unable to create process using ... 2.2 安装virtualenvwrapper-win2.3 新建一个用于人工智能环境的…

腾讯云 API 3.0(V3版签名) 通用接口 Delphi 版

目录 一、腾讯云API 3.0 简介&#xff1a; 二、Delphi 接口函数说明&#xff1a; 1. Delphi 接口包含的单元&#xff1a; 2. 同步调用和异步调用的区别&#xff1a; 3. 程序调用示例&#xff1a; 三、Delphi 版腾讯云API 3.0 版接口函数下载 四、演示程序录播 下载源程序…

DB2数据库SQL将不同行做合计

DB2数据库SQL将不同行做合计 案例&#xff1a; 将’GL’和’RZ’做合计&#xff0c;其他的不动。 SELECT SALE_TYPE,ROUND(CAST(SUM(aatp_weight) AS DOUBLE),2) AS aatp_weight FROM( SELECT CASE WHEN SALE_TYPE GL THEN RZ ELSE SALE_TYPE END AS SALE_TYPE, DEMAND_NUM / …

基于NXP iMX8MP处理器M7核心LVGL移植

By Toradex胡珊逢 LVGL (Light and Versatile Graphics Library)是一个轻量级的开源图形库&#xff0c;采用 C 或者 MicroPython 语言开发。可以在资源有限的 MCU 上轻松地绘制图形界面。Verdin iMX8M Plus 模块的处理器除了 Cortex-A53 核心外&#xff0c;还具有一个 Cortex-M…

如何运营校园外卖跑腿小程序

运营校园外卖跑腿小程序需要考虑多个方面&#xff0c;包括市场调研、合作伙伴选择、用户获取与留存、服务管理和推广等。下面是一些关键步骤和策略&#xff1a; 市场调研&#xff1a; 在开始运营之前&#xff0c;进行市场调研是非常重要的。了解目标用户的需求和习惯&#xf…

HarmonyOS学习路之方舟开发框架—方舟开发框架(ArkUI)概述

方舟开发框架&#xff08;简称ArkUI&#xff09;为HarmonyOS应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff08;组件、布局、动画以及交互事件&#xff09;&#xff0c;以及实时界面预览工具等&#xff0c;可以支持开发者进行可视化界面…

JVM系列(6)——类加载器详解双亲委派

一、类加载器 类加载器是一个负责加载类的对象&#xff0c;用于实现类加载过程中的加载这一步。 主要作用就是加载 Java 类的字节码&#xff08; .class 文件&#xff09;到 JVM 中&#xff08;在内存中生成一个代表该类的 Class 对象&#xff09;。 加载过程可以看 JVM系列&a…

人工智能-反向传播

前面阐述过&#xff0c;在设计好一个神经网络后&#xff0c;参数的数量可能会达到百万级别&#xff0c;利用梯度下降去更新参数计算复杂&#xff0c;算力不足&#xff0c;因此需要一种有效计算梯度的方法&#xff0c;这种方法就是辛顿提出的反向传播&#xff08;简称BP&#xf…

【算法基础】搜索与图论

DFS 全排列问题 842. 排列数字 - AcWing题库 #include<bits/stdc.h> using namespace std; const int N10; int n; int path[N]; bool st[N]; void dfs(int x) {if(x>n){for(int i1;i<n;i) cout<<path[i]<<" ";cout<<endl;return ;…

高级测试工程师求职之路:从笔试到面试,我经历了什么?

最近行业里有个苦涩的笑话&#xff1a;公司扛过了之前的三年&#xff0c;没扛过摘下最近的一年&#xff0c;真是让人想笑又笑不出来。年前听说政策的变化&#xff0c;大家都满怀希望觉得年后行情一片大好&#xff0c;工作岗位激增&#xff0c;至少能有更多的机会拥抱未来。然而…

【每日一题】979. 在二叉树中分配硬币

【每日一题】979. 在二叉树中分配硬币 979. 在二叉树中分配硬币题目描述解题思路 979. 在二叉树中分配硬币 题目描述 给你一个有 n 个结点的二叉树的根结点 root &#xff0c;其中树中每个结点 node 都对应有 node.val 枚硬币。整棵树上一共有 n 枚硬币。 在一次移动中&…

计算机体系结构基础知识介绍之线程级并行性及其利用

线程级并行&#xff08;Thread Level Parallelism&#xff0c;TLP&#xff09;是指在多个处理器或多个核心上同时执行多个线程&#xff0c;从而提高程序的性能和吞吐量。线程级并行的基本原理是利用程序中的数据或任务的并行性&#xff0c;将程序划分为若干个相对独立的子任务&…

c++游戏小技巧7:system 综合

目录 1.日常前言&#xff1a; 2.system 1.换标题&#xff1a;title 2.更改运行框大小 mode cons 3.清屏 cls 4.关机 shutdown 1.电脑多累啊&#xff0c;让他休息一下吧(直接关机) 2.电脑虽然很累&#xff0c;但是还想工作一会再睡(定时关机) 3.不让电脑休息的极其不友善…

【统计函数3】——excel常见函数

相关数据资料来源于网易 函数一览&#xff1a; rank、rand、randbetween、floor、int rank函数: 求某单元格在某区域内的排名 RANK(数值,引用区域,降序0/升序1)范围多指定&#xff1a; 分开的范围之间可用逗号隔开&#xff0c;最后再用一个小括号括起来。F4可以快速锁定行和列。…