【C/C++】IO流
目录
前言:
一,C语言的I/O流
二,C++的I/O流
2-1,C++标准IO流
2-2,IO流的连续输入
前言:
“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据的抽象描述。I/O是指输入输出设备。C/C++的I/O流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。它的特性是有序连续性和方向性。
一,C语言的I/O流
C语言中我们用到的最频繁的输入输出方式就是scanf()与printf()。scanf 从标准输入设备(键 盘)读取数据,并将值存放在变量中。printf 将指定的文字/字符串输出到标准输出设备(屏幕),注意宽度输出和精度输出控制。除此外C语言还提供了类似于fprintf、fscanf等等专门控制I/O的函数接口。C语言借助了相应的缓冲区来进行输入与输出(缓冲器的专门讲解:缓冲区),如下图所示:

输入输出缓冲区优点:
1,可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。
2,减少因频繁地、小块地读写数据而产生的性能开销。这里的缓冲区可一次性存入这些数据,等到刷新缓冲区时将进行输入/输出。
C语言对于I/O这块需注意缓冲区的刷新,我们来观看以下C语言的代码问题。
#include <stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码: ");
scanf("%s", password);
printf("请确认密码(Y/N): ");
char input = 0;
scanf("%c", &input); //注意:这块开始出问题
if (input == 'Y')
printf("确认成功\n");
else
printf("确认失败\n");
return 0;
}

scanf 函数的原理就是行缓冲,即输入回车('\n')就会刷新缓冲区。不过需要注意,用户最后输入的回车也会储存在缓冲区。上面代码的问题就出现在scanf的行刷新,当输入完 password 并回车后,缓冲区中还存在回车这个残留字符,当再次进行input流操作时,缓冲区将其字符赋给input并自动刷新(因为缓冲区已经没有数据了),即input == '\n',就会出现上面那种情况。这里需要将缓冲区里面残留字符给去掉或使用 fflush强制刷新缓冲区,但 fflush在有些编译器是没有的,它不属于C标准,不推荐使用。
#include <stdio.h>
int main()
{
char x = 0, y = 0;
scanf("%c", &x);
printf("x = %c\n", x);//将缓冲区中的'\n'拿出,即清理缓冲区,若需要清理大部分字符,这里要使用循环语句
getchar();
scanf("%c", &y);
if (y == '\n')
printf("y == \\n\n");
else
printf("y = %c\n", y);
return 0;
}
输出一:没有getchar清理缓冲区字符

输出二:getchar清理缓冲区字符

二,C++的I/O流
2-1,C++标准IO流
C++的I/O底层原理与C语言一样,但C++系统实现了一个庞大的类库来实现I/O流操作,其中ios为基类,其他类都是直接或间接派生自ios类。

其中,istream(输入流)和ostream(输出流)是I/O(输入/输出)流类的重要组成部分,它们定义了进行I/O操作的基本接口。cin、cout、cerr、clog都是istream和ostream的实例。这两个类及其派生类(如ifstream、ofstream等)允许程序员以一种简洁且灵活的方式与各种数据源(如文件、控制台等)进行交互。
istream(输入流)定义了从数据源(如文件、控制台等)读取数据的基本操作,它包含了一系列以 operator>>形式出现的成员函数,用于读取不同类型的数据。其中我们常用于从控制台读取数据的cin就是istream的一个实例,而cin只有把输入缓冲区中的数据取完后(即刷新缓冲区),才要求输入新的数据,补足了C语言的scanf的缺陷。
ostream(输出流)定义了向数据目标(如文件、控制台等)写入数据的基本操作,它包含了一系列以 operator<<形式出现的成员函数,用于写入不同类型的数据。其中我们常用于向控制台写入数据的cout就是ostream的一个实例,而平常与cout连用的std::endl操作符不仅插入了一个换行符,还刷新了与std::cout关联的输出缓冲区。
C++标准IO流除了cout标准输出和cin标准输入外,还有cerr用来进行标准错误的输出,以及clog进行日志的输出。从上图可以看出,cout、 cerr、clog是ostream类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同,一般情况下cout用的比较多。
C++的标准IO流之所以能够直接输出内置类型数据,是因为标准库已经将所有内置类型的输入和输出全部重载了。对于自定义类型,若需要支持cin和cout的标准输入输出,需要对 << 和 >>进行重载。


总的来说,C++的IO流是使用面向对象+运算符重载的方式实现的,它识别类型的本质是函数重载,内置类型可以直接使用是因为库里面istream/ostream类型已经实现了,自定义类型则需要自己重载<< 和 >>,也就是说C++的这种IO模式能够更好的兼容自定义类型,流插入和流提取。
2-2,IO流的连续输入
编程算法中有些情况会出现不断输入的情况,如:while (cin >> a){.....},结束输入的情况很多时候都是使用快捷键:Ctrl + c解决(Ctrl + c是向系统内部发送结束当前进程的信号,直接暴力杀死进程)。
实际上我们看到使用while (cin >> a){.....}去流中提取对象数据时,调用的是operator>>,返回值是 istream类型的对象,即while(cin >> a)实际上是while (operator>>(cin, a)),那么这里可以做逻辑条件值,源自于istream的对象又调用了operator bool(),operator bool()调用时如果接收流失败或有结束标志时,则返回false。任何类型只要想判断,只用重载一个operator bool()即可。
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)
{}
//重载bool类型,用于循环语句的判断
operator bool()
{
//这里假设输入_year为0时结束
if (_year == 0)
return false;
else
return true;
}
private:
int _year;
int _month;
int _day;
};
//实现Date类的流插入和流提取
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 d(2024, 6, 7);
cout << "输出: " << d << endl;
while (d)
{
cin >> d;
cout << "输出: " << d << endl;
}
return 0;
}

相关文章:
【C/C++】IO流
目录 前言: 一,C语言的I/O流 二,C的I/O流 2-1,C标准IO流 2-2,IO流的连续输入 前言: “流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据…...
Vite5+Vue3整合Tailwindcss详细教程
创建vite项目 执行命令: npm create vite启动项目 npm install -g pnpm pnpm i pnpm dev浏览器访问 http://localhost:5174/ 整合Tailwindcss 安装依赖 pnpm install -D tailwindcss postcss autoprefixer初始化配置文件 npx tailwindcss init用webstorm打开…...
小程序 UI 风格魅力非凡
小程序 UI 风格魅力非凡...
【常用工具系列】Git 教程——从入门到大师
目录 前言一、Git 基础1-1、Git 简介与安装安装 Git 1-2、 Git 工作流程1-3、 Git 配置与管理用户配置查看配置 1-4、 Git 仓库操作克隆仓库推送更改拉取更新 1-5 Git 分支管理创建分支切换分支删除分支解决冲突 二、 Git 进阶2-0、 Git 标签使用创建标签查看标签检出标签推送标…...
每天坚持写java锻炼能力---第一天(6.4)
今天的目标是菜单: B站/马士兵的项目菜单 package java1;import java.util.Scanner;public class Test {public static void main(String[] args) {while(true){ //3.加入死循环,让输入一直有System.out.println();System.out.println("--->项…...
mysql 如何分布式部署
MySQL的分布式部署是一个涉及多个步骤和配置的过程,以确保数据库系统能够支持大规模数据存储、高并发访问和容错性。以下是MySQL分布式部署的主要步骤和要点,结合参考文章中的相关信息进行整理: 一、前期准备 环境准备: 选择合…...
Git的概念
Git 一些概念 **工作区:**电脑上你能看到的目录 **版本库:**工作区的隐藏目录.git。含 暂存区:git add后但未git commit的文件修改被添加到暂存区本地分支:git commit后,但未git push,即把暂存区的所有…...
【每日刷题】Day58
【每日刷题】Day58 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 3038. 相同分数的最大操作数目 I - 力扣(LeetCode) 2. 868. …...
Python 的七个HTTP请求库对比
Python HTTP请求库对比 库名称特点优点缺点requests简单易用的HTTP库,基于urllib3。- 语法简洁- 社区支持强大- 易于上手和维护- 阻塞式调用,不支持异步操作- 相比aiohttp体积较大http.clientPython标准库中的低级HTTP库。- 无需安装第三方库- 提供底层…...
顶顶通呼叫中心中间件-如何配置识别不同语种的ASR
文章目录 前言联系我们创建不同语种的语音识别任务开始对接识别不同语种的ASR重启 asrproxy 程序使用识别不同语种的ASR 前言 之前讲过顶顶通的 asrproxy 程序如何对接第三方的ASR,比如:阿里云的ASR。不知道如何对接的,可以参考:…...
C# SolidWorks 二次开发-显示配置
在 SolidWorks 的二次开发中,显示配置(Display States)是一个非常重要的功能。显示配置允许用户在同一个配置(Configuration)下保存不同的显示状态,如隐藏或显示的零件、不同的颜色和材质等。本文将向新的开…...
PXE自动装机
一、PXE概述 PXE:c/s架构,允许客户端通过网络从远程服务器(服务端)下载引导镜像,加载安装文件,实现自动化安装操作系统。 c/s 架构:服务端和客户端都可以是多台。 无人值守:安装选…...
MQ之初识kafka
1. MQ简介 1.1 MQ的诞生背景 以前网络上的计算机(或者说不同的进程)传递数据,通信都是点对点的,而且要实现相同的协议(HTTP、 TCP、WebService)。1983 年的时候,有个在 MIT 工作的印度小伙突发…...
linux驱动学习(七)之混杂设备
需要板子一起学习的可以这里购买(含资料):点击跳转 一、混杂设备 混杂设备也叫杂项设备,是对普通的字符设备(struct cdev)的一种封装,设计目的就是为了简化字符设备驱动设计的流程。具有以下特点: 1) 主设备号为10&a…...
【数据结构与算法 | 堆篇】力扣215, 703
1. 力扣215 : 数组中的第k个最大元素 (1). 题 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解…...
项目经理进入职场都会经历的三个阶段
对于项目经理而言,进入职场是一个不断学习和成长的过程。在这个过程中,项目经理通常会经历三个主要阶段,每个阶段都有其独特的特点和挑战。 一、基础建设与学习阶段 对于新入行的项目经理来说,最初的阶段主要是基础技能的积累和…...
消防设施工程乙级资质全解析:申请条件与流程“
消防设施工程乙级资质全解析:申请条件与流程 消防设施工程乙级资质,作为衡量企业从事特定规模消防设施设计能力的重要标尺,对于想要在消防工程领域拓展业务的企业而言至关重要。本文将全面解析申请消防设施工程乙级资质所需的条件、流程及相…...
【C语言】03.分支结构
本文用以介绍分支结构,主要的实现方式为if语句和switch语句。 一、if语句 1.1 if语句 if (表达式)语句表达式为真则执行语句,为假就不执行。在C语言中,0表示假,非0表示真.下图表示if的执行过程: 1.2 else语句 当…...
uniapp手机屏幕左滑返回上一页支持APP,H5
核心:touchstart"touchStart" touchend"touchEnd" 代码示例: <template><view class"payPasswordSetting" touchstart"touchStart" touchend"touchEnd"></view> </template&g…...
【Java毕业设计】基于JavaWeb的洗衣店管理系统
文章目录 摘要ABSTRACT目 录1 概述1.1 研究背景及意义1.2 国内外研究现状1.3 拟研究内容1.4 系统开发技术1.4.1 SpringBoot框架1.4.2 MySQL数据库1.4.3 MVC模式 2 系统需求分析2.1 可行性分析2.2 功能需求分析 3 系统设计3.1 功能模块设计3.2 系统流程设计3.3 数据库设计3.3.1 …...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
