c++编程(27)——IO流(1)

news2024/11/13 10:39:57

欢迎来到博主的专栏:c++编程
博主ID:代码小豪

文章目录

    • 标准IO流
      • 标准输入输出
        • cin
        • cin的四个状态标志

标准IO流

<iostream>库中的IO类在之前已经经常使用了,但是我们还从未仔细的了解过。在c++标准库中,IO类分为两种,分别是输入流istream类,输出流ostream类。

cin是istream类的对象。从标准输入流中读取数据
cout是ostream类的对象,向标准输出流写入数据
cerr是ostream类的对象,向标准错误流写入数据。

IO流又细分为多种,我们先从标准IO流开始讲起

标准输入输出

cin

cin从标准输入流(通常是键盘)当中读取数据,并将数据写入缓冲区当中,当程序需要从输入流当中提取数据时,就会在缓冲区当中进行读取。

那么什么是缓冲区呢?我们可以将缓冲区想象成一个动态开辟的空间(或者是一个不显示的字符数组),当我们使用键盘输入时,实际上是输入在输入缓冲区当中,当我们敲下回车时,缓冲区的数据才会输入进程序当中。

为什么要设计出缓冲区呢?我们可以设想如果直接将键盘的数据直接写入在程序当中,第一,效率会变低,因为如果一个键一个键的读入,那么CPU就会进行大量的低级I/O操作,而使用缓冲区之后,从每个数据的读入,变成了一次性的多个数据读入,这会快很多。

第二,如果我们发生了错误写入操作,那么就可以在缓冲区当中对数据进行删除重写。方便操作。
在这里插入图片描述

cin的四个状态标志

从缓冲区写入到程序当中是会发生写入成功和写入失败这两种情况的。由于写入到缓冲区的数据不会进行区分,所以只有从缓冲区写入到程序当中就有可能出现错误了,最典型的例子就是写入的数据,与接收数据的变量的类型不匹配。而c++将cin写入程序的情况分为了4种,也就是四种状态标志。
(1)good
(2)eof
(3)fail
(4)bad

good标志说明写入成功,eof标志则是一个结束标志,表示写入操作已经结束,fail和bad标志则说明写入操作发生了错误。

而cin对象被设置了不同的状态,也会有不同的效果,在默认情况下,cin的标志为good,表示写入正常,此时cin会继续读取缓冲区的内容,而如果cin处于其他标志,则不会继续向程序写入数据。

为了让用户了解到cin对象的当前的状态,设计了四个函数。

bool good() const;
bool eof() const;
bool fail() const;
bool bad() const;

这四个函数的使用方法也很简单,如果cin设置了good标志,那么good标志就会返回true,反之为false,同理,其余函数也是以这种方式来观察当前cin对象的状态。

我们可以通过下面程序观察cin的写入情况:

void test1()
{
	int i = 0;
	while (cin >> i)
	{
		cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
		cout << i<<endl;
	}
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << i << endl;
}

这个while(cin>>i)在I/O型OJ当中常见的多行写入的程序。但似乎我们好像很少会去深究这段代码的真正的意义,现在,我们来正式的了解一下。

众所周知(如果你不知道,那么现在你也知道了),while当中的表达式结果是bool类型的,而c++标准库为istream对象重载了一个operator bool的函数。我们可以在cpp网站上看到这个函数的定义。
在这里插入图片描述
如果istream对象(比如cin),被设置了bad和fail标志,那么就会返回false,其余情况就会返回true。所以如果cin发生写入错误时或者遇到结束标志(eof)时,就会结束循环。

因此我们可以利用这段代码来分析什么情况下cin的错误标志会被设置。

情况(1)正常输入:
我们输入1111,由于接收1111的类型会是int类型,因此设置的标志会是good、程序正常读入数据。
在这里插入图片描述
此时cin的状态为:good(1),eof(0),fail(0),bad(0)。(1为ture,0为false,表示cin对象当前处于为1的状态,在本例当中,即cin对象处于good状态。)

情况2(2)设置了结束标志。
在window当中,缓冲区的结束标志eof,可以使用键盘ctrl+z进行写入,用^z表示eof,比如我们尝试一个多行输入
1111
2222
^z
在这里插入图片描述
由于cin读取到了结束标记eof,此时cin的状态为good(0),eof(1),fail(1),bad(0)。根据前面所说的,由于istream对象被设置了fail或者bad标志,因此while(cin>>i)的结果为false,此时结束多行输入。
(3)写入错误(fail)
当写入的数据与接收数据的对象类型不匹配时,就会发生写入错误。比如我们写入ss。
在这里插入图片描述
由于ss是char类型的数据,因此不能用int类型的变量来接收数据。此时cin的状态为good(0),eof(0),fail(1),bad(0)。while(cin>>i)的结果为false,结束循环。要注意,一旦cin的状态不再是good,那么cin不会再从标准输入流当中读取数据。关于cin的操作也会停止。

void test2()
{
	int i = 0;
	cin >> i;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << i << endl;

	int j = 0;
	cin >> j;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << j << endl;
}

如果我们对i进行写入的时候发生了错误(比如fail或者eof,bad标志被设置时),此时cin就会变得不可用。如果想要重新启用cin,那就要恢复cin的标志。将cin置为good即可。c++设计了两个函数用于重新设置标志码,为:
在这里插入图片描述
setstate是将一个标志码设置到cin当中,而clear则是恢复cin的默认状态,即(good(1),eof(0),fail(0),bad(0))。

void test2()
{
	int i = 0;
	cin >> i;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << i << endl;

	cin.clear();

	int j = 0;
	cin >> j;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << j << endl;
}

但是这样做也不能解决问题,这是因为缓冲区中的s由于读取失败,因而还存在与缓冲区当中,继续读取并不能解决问题,因此我们要先将缓冲区当中的字符清理掉。因此正确的方式为:
(1)恢复标志
(2)将缓冲区中的字符全部读取

void test2()
{
	int i = 0;
	cin >> i;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << i << endl;

	if (cin.fail())
	{
		string str;
		cin.clear();
		cin >> str;
	}
	
	int j = 0;
	cin >> j;
	cout << cin.good() << " " << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
	cout << j << endl;
}

情况4:
bad标志是由于缓冲区本身的错误而导致的,因此恢复错误码并清理缓冲区并不能解决问题。而是要从程序当中入手,看看程序当中有没有导致缓冲区错误的代码。

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

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

相关文章

sqli-labs靶场自动化利用工具——第2关

文章目录 概要整体架构流程技术细节执行效果小结 概要 Sqli-Labs靶场对于网安专业的学生或正在学习网安的朋友来说并不陌生&#xff0c;或者说已经很熟悉。那有没有朋友想过自己开发一个测试脚本能实现自动化化测试sqli-labs呢&#xff1f;可能有些人会说不是有sqlmap&#…

摄影社团管理系统

基于springbootvue实现的摄影社团管理系统 &#xff08;源码L文ppt&#xff09;4-075 第四章 系统概要设计 4.1系统设计原理 设计原理是指系统的设计来源&#xff0c;它将需求合理地分解为功能&#xff0c;并抽象地描述系统的模块和其下的功能。在功能模块化后&#xff…

【数据结构】排序算法---桶排序

文章目录 1. 定义2. 算法步骤3. 演示3.1 动态演示13.2 动态演示23.3 图片演示13.4 图片演示2 4. 性质5. 算法分析6. 代码实现C语言PythonJavaCGo 结语 1. 定义 桶排序&#xff08;英文&#xff1a;Bucket sort&#xff09;是计数排序的升级版&#xff0c;适用于待排序数据值域…

【算法】最长公共子序列(C/C++)

最长公共子序列&#xff08;LCS&#xff0c;Longest Common Subsequence&#xff09;问题简称&#xff08;LCS&#xff09;&#xff0c;是动态规划里面里面的基础算法。它的所解决的问题是&#xff0c;在两个序列中找到一个序列&#xff0c;使得它既是第一个序列的子序列&#…

SpringCloud微服务实现服务降级的最佳实践

Spring Cloud是一种用于快速构建分布式系统的框架&#xff0c;它提供了许多有用的功能&#xff0c;其中包括服务降级。 服务降级是一种保护机制&#xff0c;它可以在面临高并发或故障时保持服务的稳定性。当系统资源不足或服务出现故障时&#xff0c;服务降级可以通过关闭一些功…

2.计算机网络基础

2. 计算机网络基础 (1) 计算机网络的定义 计算机网络是指将地理位置不同、具有独立功能的多个计算机系统通过通信线路和设备连接起来,以功能完善的网络软件实现网络中资源共享的系统。最简单的定义是:计算机网络是一些互相连接的、自治的计算机系统的集合。最庞大的计算机网…

MATLAB系列03:分支语句和编程设计

MATLAB系列03&#xff1a;分支语句和编程设计 3. 分支语句和编程设计3.1 自上而下的编程方法简介3.2 伪代码的应用3.3 关系运算符和逻辑运算符3.3.1 关系运算符3.3.2 小心和~运算符3.3.3 逻辑运算符3.3.4 逻辑函数 3.4 选择结构3.4.1 if结构3.4.2 switch结构3.4.3 try/catch结构…

c++的decltype关键字

它可以将变量声明为表达式指定的类型

C语言程序二级 之知识点 程序填空 程序设计 程序修改

一 知识点 宏定义是指用一个宏名(名字)来代表一个字符串。宏定义的功能是在编译预处理时&#xff0c;对程序中所有出现的"宏名"都用宏定义中的字符串去代换&#xff0c;这称为"宏代换"或"宏展开"。无参宏定义的一般格式&#xff1a;#define 标识…

中国光刻机突破28nm?进步巨大但前路漫漫

在近期的报道中&#xff0c;中国国产光刻机进入推广目录的消息引发了广泛关注&#xff0c;其中提到的一款氟化亚光刻机的分辨率达到了65nm&#xff0c;被视作具备28nm制程节点的生产能力。那么&#xff0c;国产光刻机真的已经突破了28nm制程节点了吗&#xff1f;本文将对相关技…

Mysql梳理6——order by排序

目录 6 order by排序 6.1 排序数据 6.2 单列排序 6.3 多行排列 6 order by排序 6.1 排序数据 使用ORDER BY字句排序 ASC&#xff08;ascend&#xff09;:升序DESC(descend):降序 ORDER BY子句在SELECT语句的结尾 6.2 单列排序 如果没有使用排序操作&#xff0c;默认…

第157天: 安全开发-Python 自动化挖掘项目SRC 目标FOFA 资产Web 爬虫解析库

案例一&#xff1a;Python-WEB 爬虫库&数据解析库 这里开发的内容不做过多描述&#xff0c;贴上自己写的代码 爬取数据 要爬取p标签&#xff0c;利用Beautyfulsoup模块 import requests,time from bs4 import BeautifulSoup#url"https://src.sjtu.edu.cn/rank/firm…

教你建设智慧数字乡村如何选供应商,如何落地项目

说到数字乡村建设&#xff0c;大家都有自己的思路和想法&#xff0c;那么如果现在让你来做这个项目你又如何来实施&#xff1f;都需要什么方式&#xff1f;都要具备什么条件&#xff1f; 下面我来说一下我的个人思路&#xff0c;要做数字乡村我觉得前提是必须满足几个条件&…

可视化工具Gephi安装要求和特点

Gephi是进行社会图谱数据可视化分析的工具&#xff0c;不但能处理大规模数据集并且Gephi是一个可视化的网络探索平台&#xff0c;用于构建动态的、分层的数据图表。 Gephi安装要求 ① gephi是一个可多平台使用的绘图软件&#xff0c;能在Windows&#xff0c;OS&#xff0c;Lin…

平价头戴式蓝牙耳机有哪些?四款公认平价性能超强品牌机型推荐

在追求高品质音乐体验的同时&#xff0c;许多消费者希望找到价格亲民的头戴式蓝牙耳机&#xff0c;市场上不乏性能卓越、价格实惠的产品&#xff0c;它们凭借出色的音质、舒适的佩戴体验和可靠的续航能力赢得了用户的青睐&#xff0c;那么在众多的头戴式蓝牙耳机内&#xff0c;…

英伟达:AI时代的领跑者,引领智能计算的未来@附149页PDF文件下载

在人工智能的浪潮中&#xff0c;英伟达&#xff08;NVIDIA&#xff09;以其卓越的GPU技术&#xff0c;成为了这个时代的领跑者。从游戏显卡的霸主到AI计算的领导者&#xff0c;英伟达的转型之路充满了创新与突破。今天&#xff0c;我们将深入探讨2024年英伟达如何通过其战略布局…

Python 中的异步编程:从入门到实践

在现代编程实践中&#xff0c;异步编程已经成为一个不可或缺的技能&#xff0c;尤其是在处理高并发和I/O密集型应用时。Python&#xff0c;作为一种动态、解释型的高级编程语言&#xff0c;提供了强大的异步编程支持&#xff0c;使得开发者能够有效地编写高效、可扩展的应用程序…

虹科技术 | Linux环境再升级:PLIN驱动程序正式发布

Linux驱动程序领域再添新成员&#xff0c;PLIN驱动程序现已正式发布。这一新驱动程序为使用LIN接口的用户提供了一个便捷、高效的解决方案。本文将展示如何安装PLIN驱动程序&#xff0c;以及如何在Linux环境下进行基本的PLIN通信操作&#xff0c;确保您能够快速掌握并应用这一新…

寄存器二分频电路

verilog代码 module div2_clk ( input clk, input rst,output clk_div);reg clk_div_r; assign clk_div clk_div_r;always(posedge clk) beginif(rst)beginclk_div_r < 1b0;endelsebeginclk_di…

射击靶标检测系统源码分享

射击靶标检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…