I/O流(C++)

输入输出操作是程序中必不可少的操作,通过输入输出可以完成程序和外界的交互。

C++语言支持两种I/O操作:

(1)从C语言继承来的I/O函数输入输出语句:scanf()、printf()函数

(2)面向对象的I/O流类库:标准输入输出流cout和cin,在头文件iostream.h中定义。 I/O流不是C++语言的一部分,而是标准C++库的一部分,是C++类的一个集合

一、C++中的输入输出

C语言中我们用的输入输出方式是:scanf() 和 printf()

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

  • printf():将指定的变量或字符串输出到标准输出设备(屏幕)

  • C语言借助了输入缓冲区和输出缓冲区来进行输入输出

注意:设备是输入输出设备,代码是变量或对象(在虚拟内存中开辟空间存储值)

对输入输出缓冲区的理解:

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

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

二、流是什么

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

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

总结:

1、流的特点是有序连续、具有方向性。
2、为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能。

三、C++的I/O流

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类。

3.1、C++的标准I/O流

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

  • 使用cout进行标准输出,即数据从内存流向控制台(显示器)

  • 使用cin进行标准输入即数据通过键盘输入到程序中,同时C++标准库还提供了cerr用来进行标准错误的输出,以及clog进行日志的输出

  • 从上面I/O流的设计图可以看出,cout、cerr、clog是ostream类的三个不同的对象,本质上他们都是同一个类的对象,只是应用场景不同

#include <iostream>
using namespace std;

int main()
{
	int i = 0;
	// 对象流入输出设备,在显示器中打印对象中存储的值
	cout << i << endl;
	cerr << i << endl;
	clog << i << endl;
	return 0;
}

在使用时候必须要包含文件并引入std标准命名空间

注意:

1、cin为缓冲流,键盘输入的数据会被保存在输入缓冲区中,当要提取时,是从这里拿的如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把缓冲区中的数据读取完后,才能重新输入新的数据

2、输入的数据类型必须与要提取的数据类型一致,否则会出错,流的错误标识会置1,程序继续

3、空格和回车可以作为数据之间的间隔符,连续输入时以间隔符隔开即可。如果输入的是字符和字符串时,不能输入空格(ASII码为32),字符串也不能有空格,回车无法写入

4、cin和cout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了,自定义类型需要自己重载

5、对于自定义类型,如果要支持cin和cout的标准输入输出,需要对<<和>>进行重载

     

【流输入】:

【流输出】:

void Test()
{
	// 自动识别类型的本质--函数重载
	// 内置类型可以直接使用--因为库里面ostream类型已经实现了
	int i = 1;
	double j = 2.2;
	cout << i << endl;
	cout << j << endl;
}

istream类型对象转换为逻辑条件判断值:
【operator<<】【operator bool】

        实际上我们看到使用while(cin>>i)去流中提取对象数据时,调用的是operator>>,返回值是istream类型的对象

        那么这里可以做逻辑条件值,源自于istream的对象又调用了operator bool,operator bool调用时判断,如果接收流失败,或者有结束标志,则返回false

6. 在线 OJ 中的输入和输出:
        对于IO 类型的算法,一般都需要循环输入:
        输出:严格按照题目的要求进行,多一个少一个空格都不行。
        连续输入时,vs 系列编译器下在输入 ctrl+Z 时结束
// 单个元素循环输入
while(cin>>a)
{
    // ...
}
// 多个元素循环输入
while(c>>a>>b>>c)
{
    // ...
}
// 整行接收
while(cin>>str)
{
    // ...
}

3.2 C++文件IO

C++根据文件内容的数据格式分为二进制文件和文本文件

使用文件流对象操作文件的方法:

1、定义一个文件流对象
        ifstream ifile(只输入用)

        ofstream ofile(只输出用)

        fstream iofile(输入输出用)

2、使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系

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

4、关闭文件(一般不用写,因为文件流是一个类,类自动调用析构关闭文件)

基本的文件流对象读写文件

定义一个使用二进制和文本读写的类

struct ServerInfo
{
	char _adress[256];
	int _port;
};

struct  ConfigManager
{
public:
	ConfigManager(const char* filename)
		: _filename(filename)
	{}

	// 以二进制的形式写文件
	void WriteBin(ServerInfo& info)
	{
		// 输出文件流要设置二个状态,第一个是默认输出第二个二进制输出
		ofstream ofs(_filename, std::ios::out | std::ios::binary);
		ofs.write((const char*)&info, sizeof(info));
	}

	// 以二进制的形式读文件
	void ReadBin(ServerInfo& info)
	{
		// 这里也要设置二个状态,第一个为默认,第二个binary
		ifstream ifs(_filename, std::ios::in | std::ios::binary);
		ifs.read((char*)&info, sizeof(info));
	}

	///

	// 以文本的方式写文件
	void WriteTxt(ServerInfo& info)
	{
		ofstream ofs(_filename, std::ios::out);
		// 注意写到文件要加空格或回车这二个分隔符,不然读文件的时候会读不到,因为读的是以分隔符来判断是否读完
		ofs << info._adress << endl;
		ofs << info._port << endl;
	}

	// 以文本的方式读文件
	void ReadTxt(ServerInfo& info)
	{
		ifstream ifs(_filename, std::ios::in);
		ifs >> info._adress >> info._port;
	}
public:
	string _filename; // 配置文件
};

void Test3()
{
	ServerInfo info = { "https://www.bilibili.com/video/BV1Dd4y1U7AE?p=61&spm_id", 100 };
	ConfigManager cfm("D:\\test.bin");

	// 二进制方式写文件
	cfm.WriteBin(info);

	// 二进制方式读文件
	ServerInfo info2;
	cfm.ReadBin(info2);
	cout << info2._adress << endl;
	cout << info2._port << endl;

	///

	ServerInfo info3 = { "https://mooc1.chaoxing.com/mycourse/studentstudy?chapterId=444012113&courseId=227786429&clazzid", 200 };
	ConfigManager cfm2("D:\\test.txt");

	// 以文本的方式写文件
	cfm2.WriteTxt(info3);

	// 以文本的方式读文件
	ServerInfo info4;
	cfm2.ReadTxt(info4);
	cout << info4._adress << endl;
	cout << info4._port << endl;
}

注意:

1、文件流对象的第二个参数这样写时:std::ios::in | std::ios::binary,意思是in 和 binary状态按位或在一起,当我们要以二进制读或写时,编译器会拿这个状态跟它按位与判断有没有这个状态

2、以文本的方式写文件时,要注意间隔符,否则写入文件时会发生错误,导致随机数

四、stringstream

C语言中,将一个整形数据转换成一个字符串格式时,该怎么做?

  1. 使用itoa函数

  2. 使用sprintf函数

  • 但是两个函数在转化时,都得需要先给出保存结果的空间,那空间要给多大呢,就不太好给定,而且转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃
#include <stdio.h>
#include <stdlib.h>

void Test()
{
	int n = 123456789;
	char str1[256];
	itoa(n, str1, 10);
	printf("%s\n", str1);

	char str2[256];
	sprintf(str2, "%d", n);
	printf("%s\n", str2);

	char str3[256];
	sprintf(str2, "%f", n);
	printf("%s\n", str2);
}

int main()
{
	Test();
	return 0;
}

在C++中,可以使用stringstream类对象来避开此问题

  1. 定义一个stringstream流对象:
  • istreamstream ifile(只输入用)

  • ostringstream ofile(只输出用)

  • stringstream iofile(输入输出用

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

#include<sstream>
int main()
{
	int a = 12345678;
	string sa;
	// 将一个整形变量转化为字符串,存储到string类对象中
	stringstream s;
	s << a;
	s >> sa;
	
	// clear()
	// 注意多次转换时,必须使用clear将上次转换状态清空掉
	// stringstreams在转换结尾时(即最后一个转换后),会将其内部状态设置为badbit
	// 因此下一次转换是必须调用clear()将状态重置为goodbit才可以转换
	// 但是clear()不会将stringstreams底层字符串清空掉
	
	// s.str("");
	// 将stringstream底层管理string对象设置成"",
	// 否则多次转换时,会将结果全部累积在底层string对象中
	
	s.str("");
	s.clear(); // 清空s, 不清空会转化失败
	double d = 12.34;
	s << d;
	s >> sa;
	
	string sValue;
	sValue = s.str(); // str()方法:返回stringsteam中管理的string类型
	cout << sValue << endl;
	return 0;
}

        3.字符串拼接

void Test8()
{
	stringstream sstream;
	// 将多个字符串放入 sstream 中
	sstream << "first" << " " << "string,";
	sstream << " second string";
	cout << "strResult is: " << sstream.str() << endl;

	// 清空 sstream
	sstream.str("");
	sstream << "third string";
	cout << "After clear, strResult is: " << sstream.str() << endl;
}

        4.序列化和反序列化结构数据

struct ChatInfo
{
	string _name;	// 名字
	int _id;		// id
	Date _date;		// 时间
	string _msg;	// 聊天信息
};
void Test9()
{
	// 结构信息序列化为字符串
	ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧"};
	ostringstream oss;
	oss << winfo._name << " " << winfo._id << " " << winfo._date << " "
		<< winfo._msg;
	string str = oss.str();
	cout << str << endl << endl;

	// 我们通过网络这个字符串发送给对象,实际开发中,信息相对更复杂,
	// 一般会选用Json、xml等方式进行更好的支持
	// 字符串解析成结构信息
	ChatInfo rInfo;
	istringstream 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;
}

注意:

  1. stringstream实际是在其底层维护了一个string类型的对象用来保存结果

  2. 多次数据类型转化时,一定要用clear()来清空,才能正确转化,但clear()不会将stringstream底层的string对象清空

  3. 可以使用s. str(“”)方法将底层string对象设置为""空字符串

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动画法则与动画曲线解析

先介绍一些和代码关系不大的动画常识 挤压与拉伸(Squeeze and stretch) 当有力作用到物体身上时,物体将会产生一定的形变,比如你在拍球时,球落地后会被挤压,弹起时会产生拉伸,对于具体的挤压与拉伸的强度,与物体的硬度和用力的大小有关。做动画要遵循运动规律让动画更…

一周学会Django5 Python Web开发-Http请求HttpRequest请求类

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计25条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

JavaWeb 自己给服务器安装SQL Server数据库遇到的坑

之前买的虚拟主机免费送了一个SQL Server数据库&#xff0c;由于服务器提供商今年下架我用的那款虚拟主机产品&#xff0c;所以数据库也被收回了。我买了阿里云云服务器&#xff0c;但是没有数据库&#xff0c;于是自己装了一个SQL Server数据库&#xff0c;总结一下遇到的坑。…

【设计模式】5种创建型模式详解

创建型模式提供创建对象的机制,能够提升已有代码的灵活性和复用性。 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。不常用的有:原型模式。一、单例模式 1.1 单例模式介绍 1 ) 定义 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模…

Temu、亚马逊店铺如何快速得到好评?自养号测评下单的秘籍及必备条件。

Temu、亚马逊店铺如何快速得到好评?在这个竞争激烈的电商平台上&#xff0c;好评是店铺吸引顾客、建立良好声誉的关键。快速积累好评不仅能够提高商品的曝光度&#xff0c;也有助于吸引更多潜在顾客的关注。 然而&#xff0c;亚马逊不同于国内电商&#xff0c;对于操纵评论、…

数据清洗处理实战:将储存为股票代码的列表文件转换为pythoh列表

一、读取市场所有股票代码,并将处理过的股票代码写入文件&#xff0c;供后续使用 # 读取市场所有股票代码&#xff0c;并存入txt文件symbols xtdata.get_stock_list_in_sector(沪深A股)with open(symbols.txt,w) as f:f.write(str(symbols))由于python不能直接将列表写入txt文…

低代码流程加签功能深度解析:提升审批流程效率与准确性的利器

在流程审批过程中&#xff0c;流程加签通常是为了证明某个事项已经得到了确认或批准&#xff0c;或者为了证明某个文件已经经过了相关人员的审核或批准&#xff0c;或者除当前固定审批人外还需要额外的审批意见&#xff0c;需要临时添加其他审批人参与审批。通过流程加签配置&a…

编程的基础:理解时间和空间复杂度

编程的基础&#xff1a;理解时间和空间复杂度 时间复杂度空间复杂度示例常数时间复杂度 O(1)线性时间复杂度 O(n)线性对数时间复杂度 O(n log n)二次时间复杂度 O(n^2)指数时间复杂度 O(2^n) 空间复杂度示例常数空间复杂度 O(1)线性空间复杂度 O(n)线性对数空间复杂度 O(log n)…

leetcode hot100 买卖股票最佳时机3

本题中&#xff0c;依旧可以采用动态规划来进行解决&#xff0c;之前的两个题我们都是用二维数组dp[i][2]来表示的&#xff0c;其中i表示第i天&#xff0c;2表示长度为2&#xff0c;其中0表示不持有&#xff0c;1表示持有。 本题中&#xff0c;说至多完成两笔交易&#xff0c;也…

JAVA集合进阶(Set、Map集合)

一、Set系列集合 1.1 认识Set集合的特点 Set集合是属于Collection体系下的另一个分支&#xff0c;它的特点如下图所示 下面我们用代码简单演示一下&#xff0c;每一种Set集合的特点。 //Set<Integer> set new HashSet<>(); //无序、无索引、不重复 //Set<…

docker安装mongodb

1.使用docker安装mongo 1.1下载MongoDB镜像 docker pull mongo:4.4 1.2运行MongoDB容器 docker run -itd --name mongo -v /docker_volume/mongodb/data:/data/db -p 27017:27017 mongo:4.4 --auth 2.创建用户 2.1 登录mongo容器&#xff0c;并进入到【admin】数据库 dock…

gnss 自然灾害监测预警系统是什么

【TH-WY1】GNSS自然灾害监测预警系统是一种基于全球导航卫星系统&#xff08;GNSS&#xff09;技术的自然灾害监测和预警系统。它利用GNSS的高精度定位技术&#xff0c;通过在地表布置GNSS接收设备&#xff0c;实时监测地表形变、位移、沉降等参数&#xff0c;从而实现对自然灾…

蓝桥杯-答疑

原题链接&#xff1a;用户登录 答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序&#xff0c;同学们要依次进入老师办公室答疑。一位同学答疑的过程如下 1.首先进入办公室&#xff0c;编号为 的同学需要 s&#xff0c;…

【智慧零售】门店管理设备解决方案,为企业数字化运营升级赋能

2023年我国零售总额超47万亿元&#xff0c;广阔的市场提供了更多机遇&#xff0c;同时随着日趋激烈的竞争&#xff0c;企业也正面临着一些挑战&#xff1a;如何才能有效提升门店生产效率&#xff1f;降低门店运营成本&#xff1f;提高市场竞争力&#xff1f; 零售企业认识到通…

视频和音频使用ffmpeg进行合并

1.下载ffmpeg 官网地址&#xff1a;https://ffmpeg.org/download.html 2.配置环境变量 此电脑右键点击 属性 - 高级系统配置 -高级 -环境变量 - 系统变量 path 新增 文件的bin路径 3.验证配置成功 ffmpeg -version 返回版本信息说明配置成功4.执行合并 ffmpeg -i 武家坡20…

FullCalendar日历组件:进行任务增删改,参考gitee例子修改

效果 参考路径 zxj/FullCalendar开发示例 - 码云 - 开源中国 (gitee.com) 代码 主页面&#xff1a;codeset.php <?php ob_start(); include(includes/session.inc); ?> <!DOCTYPE html> <html><head><title>日程管理</title><met…

基于频率增强的数据增广的视觉语言导航方法(VLN论文阅读)

基于频率增强的数据增广的视觉语言导航方法&#xff08;VLN论文阅读&#xff09; 摘要 视觉和语言导航&#xff08;VLN&#xff09;是一项具有挑战性的任务&#xff0c;它需要代理基于自然语言指令在复杂的环境中导航。 在视觉语言导航任务中&#xff0c;之前的研究主要是在空间…

海南云仓酒庄拜会三亚市贸促会与三亚国际商会共谋发展 共绘蓝图

2024年2月23日上午&#xff0c;三亚市贸促会党组书记、会长、三亚国际商会会长方玉来在三亚国际商会会议室与海南云仓酒庄有限公司党支部书记蒋义一行进行了深入座谈交流&#xff0c;本次还有副会长张成山、秘书处副秘书长孙秋丽、李婧参加了座谈会。此次座谈会旨在加强双方的合…

JavaScript+PHP实现视频文件分片上传

摘要 视频文件分片上传&#xff0c;整体思路是利用JavaScript将文件切片&#xff0c;然后循环调用上传接口 upload.php 将切片上传到服务器。这样将由原来的一个大文件上传变为多个小文件同时上传&#xff0c;节省了上传时间&#xff0c;这就是文件分片上传的其中一个好处。 上…

基于SpringBoot+Apache ECharts的前后端分离外卖项目-苍穹外卖(十八)

数据展示 1. Apache ECharts1.1 介绍1.2 入门案例 2. 营业额统计2.1 需求分析和设计2.1.1 产品原型2.1.2 接口设计 2.2 代码开发2.2.1 VO设计2.2.2 Controller层2.2.3 Service层接口2.2.4 Service层实现类2.2.5 Mapper层 2.3 功能测试 3. 用户统计3.1 需求分析和设计3.1.1 产品…