【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都是istreamostream的实例。这两个类及其派生类(如ifstreamofstream等)允许程序员以一种简洁且灵活的方式与各种数据源(如文件、控制台等)进行交互。

        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;
}

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

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

相关文章

新品发布 | 飞凌嵌入式RK3576核心板,为AIoT应用赋能

为了充分满足AIoT市场对高性能、高算力和低功耗主控日益增长的需求&#xff0c;飞凌嵌入式全新推出基于Rockchip RK3576处理器开发设计的FET3576-C核心板&#xff01; 集成4个ARM Cortex-A72和4个ARM Cortex-A53高性能核&#xff0c;内置6TOPS超强算力NPU&#xff0c;为您的AI…

【RK3568】制作Android11开机动画

Android 开机 logo 分为两种&#xff1a;静态显示和动态显示。静态显示就是循环显示一张图片&#xff1b;动态显示就是以特定帧率顺序显示多张图片 1.准备 android logo 图片 Android logo最好是png格式的&#xff0c;因为同一张图片的情况下&#xff0c;png 格式的比 jpg和b…

海思SS928(SD3403)部署YOLOv5-YOLOv7步骤详解

1. YOLO模型资料 本文档内容以yolov5-7.0工程、yolov5s模型为例。 a. 模型结构 详细的模型结构可以利用netron工具打开.pt或.onnx模型查看。 b. 模型参数即验证结果 其中,YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x为五种类型的预训练模型,其包含的检测类别相…

呆滞物料规范管理了,问题就好办了

对于制造企业来说&#xff0c;库存是生存和发展的重要保障&#xff0c;过高的库存会占用企业大量的资金和管理成本&#xff0c;影响企业的正常生产&#xff0c;然而多数中小制造企业还在用人工干预管理&#xff0c;如何控制呆滞物料成为仓储管理的一大难题。 什么是呆滞料&…

Django 创建项目及应用

1&#xff0c;安装 Django pip install Django3.1.5 2&#xff0c;创建 Django项目 django-admin startproject myshop 3&#xff0c;创建 Django应用 python manage.py startapp app1 4&#xff0c;启动 Django项目 python .\manage.py runserver 到这里项目及应用创建…

Redis中的主从复制

分布式系统中的几种Redis部署方式 为了解决一个程序只部署在一个服务器上的单点问题&#xff1a; 可用性问题&#xff0c;如果这个机器挂了&#xff0c;就意味着服务就中断了 一个程序只部署在一台机器上&#xff0c;它的性能/支持的并发量也是有限的 所以&#xff0c;就引…

型号FM152A,FM148R和利时

型号FM152A,FM148R和利时。控制系统的仿真,综合考虑多方面的因素,本文将用MCGS组态软件设计一个仿真实验监控平台来对其进行实时控制.&#xff0c;完成仿真实验监控平台的设计,型号FM152A,FM148R和利时。最终达到对水箱液位实时监控,实验数据采集,报表的输出和数据的同步显示MC…

PDF分页处理:技术与实践

引言 在数字化办公和学习中&#xff0c;PDF文件因其便携性和格式稳定性而广受欢迎。然而&#xff0c;处理大型PDF文件时&#xff0c;我们经常需要将其拆分成单独的页面&#xff0c;以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…

设置电脑定时关机

1.使用快捷键winR 打开运行界面 2.输入cmd &#xff0c;点击确认&#xff0c;打开命令行窗口&#xff0c;输入 shutdown -s -t 100&#xff0c;回车执行命令&#xff0c;自动关机设置成功 shutdown: 这是主命令&#xff0c;用于执行关闭或重启操作。-s: 这个参数用于指定执行关…

C++ DFS

子集 78. 子集 法一&#xff1a;思路对每个元素进行选与不选的 选择&#xff0c;这样正好到最后一层 就是2的size()次方个&#xff0c;叶子就是节点&#xff0c;通过pos来控制深度 法二&#xff1a;通过for循环实现&#xff0c;且下一个栈帧的i是上一个栈帧当前元素的下一个位…

【上篇】从 YOLOv1 到 YOLOv8 的 YOLO 物体检测模型历史

YOLO 型号之所以闻名遐迩,主要有两个原因:其速度和准确性令人印象深刻,而且能够快速、可靠地检测图像中的物体。 在本文中,我将与大家分享我在阅读一篇长达 30 页的综合性论文时获得的见解,该论文深入探讨了 YOLO 模型的进步。 这篇评论全面概述了 YOLO 框架的演变过程,…

PDF转图片工具

背景&#xff1a; 今天有个朋友找我&#xff1a;“我有个文件需要更改&#xff0c;但是文档是PDF的&#xff0c;需要你帮我改下内容&#xff0c;你是搞软件的&#xff0c;这个对你应该是轻车熟路了吧&#xff0c;帮我弄弄吧”&#xff0c;听到这话我本想反驳&#xff0c;我是开…

PVE管理虚拟机节点

今天使用PVE命令安装虚拟机。 ‍ 查看所有虚拟机 qm list 查看所有虚拟机 ​​ 创建虚拟机 qm create 创建虚拟机 qm create 106 --name vm-test --memory 2048 --net0 virtio,bridgevmbr0基础配置 这条命令会创建一个 VM&#xff0c;ID 为 106​&#xff0c;名称为 myvm​…

Huawei 大型 WLAN 组网 AC 间漫游

AC1配置命令 <AC6005>display current-configuration # vlan batch 100 # interface Vlanif100description to_S3_CAPWAPip address 10.0.100.254 255.255.255.0 # interface GigabitEthernet0/0/1port link-type trunkport trunk allow-pass vlan 100# ip route-stati…

前端开发高频面试题

好的&#xff0c;以下是对您提出的问题的详细回答&#xff1a; 说说vue动态权限绑定渲染列表&#xff08;权限列表渲染&#xff09; Vue中动态权限绑定渲染列表通常涉及以下步骤&#xff1a; 首先&#xff0c;通过API请求从服务器获取当前用户的权限数据。在Vue组件中&#xff…

UR机器人通信汇总

文章目录 一、概述二、UR机器人通信2.1UR通信协议2.2 UR通信端口 三、UR机器人通信端口类型3.1 Modbus TCP端口&#xff08;502端口&#xff09;3.2 Dashboard端口&#xff08;29999端口&#xff09;3.3 上位机编程端口&#xff08;30001/30002/30003端口&#xff09;3.3.1 URS…

vivado HW_BITSTREAM、HW_CFGMEM

HW_比特流 描述 从比特流文件创建的硬件比特流对象hw_bitstream&#xff0c;用于关联 在Vivado的硬件管理器功能中使用硬件设备对象hw_device 设计套件。 比特流文件是从具有write_bitstream的放置和路由设计创建的 命令硬件位流对象是使用 create_hw_bitstream命令&#xff0c…

概率论与数理统计,重要知识点——全部公式总结

二、一维随机变量及其分布 五个分布参考另外一篇文章 四、随机变量的数字特征 大数定理以及中心极限定理 六、数理统计

【iOS】UI——关于UIAlertController类(警告对话框)

目录 前言关于UIAlertController具体操作及代码实现总结 前言 在UI的警告对话框的学习中&#xff0c;我们发现UIAlertView在iOS 9中已经被废弃&#xff0c;我们找到UIAlertController来代替UIAlertView实现弹出框的功能&#xff0c;从而有了这篇关于UIAlertController的学习笔记…

【数据结构】六种排序实现方法及区分比较

文章目录 前言插入排序希尔排序选择排序堆排序快速排序冒泡排序总结 前言 众所周知&#xff0c;存在许多种排序方法&#xff0c;作为新手&#xff0c;最新接触到的就是冒泡排序&#xff0c;这种排序方法具有较好的教学意义&#xff0c;但是实用意义不高&#xff0c;原因就在于…