深蓝学院C++基础与深度解析笔记 第 7 章 深入 IO

news2024/11/16 4:49:51

1. IOStream 概述(I:输入,O:输出)

●IOStream 采用流式 I/O 而非记录 I/O (类似于数据库),但可以在此基础上引入结构信息
● 所处理的两个主要问题:

– 表示形式的变化:使用格式化 / 解析在数据的内部表示与字符序列间转换
– 与外部设备的通信:针对不同的外部设备(终端、文件、内存)引入不同的处理逻辑

● 所涉及到的操作

– 格式化 / 解析
– 缓存
– 编码转换
– 传输

● 采用模板来封装字符特性,采用继承来封装设备特性

– 常用的类型实际上是类模板实例化的结果

eg: ifstream,使用模板逐步细化
在这里插入图片描述

2. 输入与输出

输入与输出分为格式化与非格式化两类
**A、非格式化 I/O :**不涉及数据表示形式的变化,非格式化对人类阅读很不友好

– 常用输入函数: get(一个) / read (多个)/ getline(一行) / gcount(缓存里剩余的)
– 常用输入函数: put(一个) / write(多个)

B、 格式化 I/O : 使用移位操作符来进行的输入 (>>) 与输出 (<<)

– C++通过操作符重载以支持内建数据类型的格式化 I/O
– 可以通过重载操作符以支持自定义类型的格式化 I/O

● 格式控制

setf()
– 可接收位掩码类型( showpos 修改某一位 )、字符类型( fill() 填充参数字符)与取值相对随意( width() ,可以接收整数,加参数个空格)的格式化参数
– 注意 width() 方法的特殊性:触发后被重置  

补充:关于showpos
在C++中,showpos是一个用于控制输出流的格式标志,它在输出正数时显示加号(+),而在输出负数时显示负号(-)。它主要用于调整输出的格式,使得输出的数值更易读。

要使用showpos标志,你需要包含<iostream>头文件,并使用std::showpos函数或使用std::ios_base::showpos成员函数来设置输出流的格式标志。

下面是一个使用showpos的简单示例:

#include <iostream>

int main() {
    int number = 10;
    double value = -3.14;

    std::cout << std::showpos;         // 设置输出流的格式标志为showpos(+-)
    std::cout << number << std::endl;  // 输出:+10
    std::cout << value << std::endl;   // 输出:-3.14

    return 0;
}

在上面的示例中,通过设置std::coutshowpos标志,输出的整数number在前面显示了一个加号,而输出的浮点数value在前面显示了一个负号。

需要注意的是,showpos标志仅影响整数和浮点数类型的输出,对于其他类型(如字符串、字符等)则不起作用。另外,showpos标志是一个永久性的标志,即一旦设置后,后续的输出将一直保持该格式,除非通过其他方式取消设置。

如果你想取消showpos标志的设置,可以使用std::noshowpos函数或std::ios_base::noshowpos成员函数来清除输出流的格式标志。例如:

std::cout << std::noshowpos;  // 取消showpos标志的设置

这样,后续的输出将不再显示加号或负号。
● 操纵符

– 简化格式化参数的设置
– 触发实际的插入与提取操作

setw()函数是定义在头文件中的一个函数,用于设置输出流中字段的宽度。
注意:setw()函数触发后被重置 ,只影响其后的输出项,即只对紧随其后的输出产生作用。如果想要持久设置输出流的字段宽度,可以使用std::setfill()函数。

另外,需要包含头文件才能使用setw()函数。

● 提取会放松对格式的限制,例如输入 ‘+a’只输出‘+’;
● 提取 C 风格字符串时要小心内存越界:
在这里插入图片描述
避免方法:可以使用setw()设置边界:
在这里插入图片描述

3. 文件与内存操作

A、 文件操作

  • basic_fstream: basic_ifstream (读取)/ basic_ofstream(写入)
    ifstream和ofstream是C++标准库中用于文件输入和输出的两个类。它们都是从基类fstream派生而来。
  • 文件流可以处于打开 / 关闭两种状态,处于打开状态时无法再次打开,只有打开时才能 I/O。
  • 当使用std::ofstream outFile(“my_file”); 这种方式时,不必进行打开关闭动作,程序会自动打开关闭的。或者使用一个域。

一般都是先写入缓存,再写到终端/文件中去

B、 文件流的打开模式

– 每种文件流都有缺省的打开方式
– 注意 ate 与 app 的异同
– binary 能禁止系统特定的转换
– 避免意义不明确的流使用方式(如 ifstream + out )

缺省的打开例子:在这里插入图片描述

C、六种文件流的打开模式:在这里插入图片描述
in | out 读写文件时,打开文件一般位于文件开头;
ate:起始位置位于文件末尾,这个位置可以移动
app: 起始位置位于文件末尾,这个位置不可以移动

D、合理的文件打开组合:
在这里插入图片描述
E、内存流相关
● 内存流: basic_istringstream / basic_ostringstream / basic_stringstream
● 也会受打开模式: in / out / ate / app 的影响
● 使用 str() 方法获取底层所对应的字符串
– cpp风格的字符串.c_str()是合理的
– 小心使用 str().c_str() 的形式获取 C 风格字符串,以下为指向一块已经释放的内存,即未定义:
在这里插入图片描述
● 基于字符串流的字符串拼接优化操作
在这里插入图片描述

4. 流的状态、定位与同步

A、流的状态
iostate
– failbit / badbit / eofbit / goodbit:在这里插入图片描述

● 检测流的状态
good( ) / fail() / bad() / eof() 方法
– 转换为 bool 值(参考cppreference)
在这里插入图片描述
从级别来看:fail() < bad()

● 注意区分 fail 与 eof
– 可能会被同时设置,但二者含意不同
– 转换为 bool 值时不会考虑 eof
eof 表示到了尾部的位置
● 通常来说,只要流处于某种错误状态时,插入 / 提取操作就不会生效
● 复位流状态

– clear :设置流的状态为具体的值(缺省为 goodbit )
– setstate :将某个状态附加到现有的流状态上

● 捕获流异常:exceptions方法
在这里插入图片描述

B、流的定位
● 获取流位置
tellg() / tellp() 可以用于获取输入 / 输出流位置 (pos_type 类型 )
– 两个方法可能会失败,成功时为当前可以输入的位置指示器,若流失败、异常时候会出现失败则为 pos_type(-1)

#include <iostream>
#include <sstream>
int main()
{
    std::ostringstream s;
    std::cout << s.tellp() << '\n';
    s << 'h';
    std::cout << s.tellp() << '\n';
    s << "ello, world ";
    std::cout << s.tellp() << '\n';
    s << 3.14 << '\n';
    std::cout << s.tellp() << '\n' << s.str();
}

输出:

0
1
13
18
hello, world 3.14

● 设置流位置
seekg() / seekp() 用于设置输入 / 输出流的位置
– 这两个方法分别有两个重载版本:
● 设置绝对位置:传入 pos_type 进行设置
● 设置相对位置:
通过偏移量(字符个数 ios_base::beg ) + 流位置符号的方式设置

– ios_base::beg 
– ios_base::cur
– ios_base::end

seekg():设置当前关联 streambuf 对象的输入位置指示器。

#include <iostream>
#include <string>
#include <sstream>
 
int main()
{
    std::string str = "Hello, world";
    std::istringstream in(str);
    std::string word1, word2;
 
    in >> word1;
    in.seekg(0); // 回溯
    in >> word2;
 
    std::cout << "word1 = " << word1 << '\n'
              << "word2 = " << word2 << '\n';
}

C、流的同步
● 基于 flush() / sync() / unitbuf 的同步

flush() 用于输出流同步,刷新缓冲区
– sync()  用于输入流同步,其实现逻辑是编译器所定义的
– 输出流可以通过设置 unitbuf 来保证每次输出后自动同步

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
unitbuf 会立即刷新,但是会影响性能

补充:std::cout 和std::cerro有什么区别?
std::coutstd::cerr 是 C++ 标准库中用于输出的流对象,但它们在以下几个方面有所不同:

  1. 输出位置: std::cout 对应标准输出流(stdout),而 std::cerr 对应标准错误流(stderr)。这意味着通过 std::cout 输出的内容会显示在正常的输出中,而 std::cerr 输出的内容则被视为错误信息,并显示在错误流中。

  2. 缓冲机制: std::cout 使用标准输出缓冲区,而 std::cerr 使用非缓冲的错误流。这意味着 std::cout 输出的内容通常会在缓冲区满、换行符出现或程序正常终止时刷新并显示,而 std::cerr 的输出则会立即显示,无需等待缓冲区刷新。

  3. 用途: std::cout 主要用于一般的标准输出,例如打印程序的正常输出、结果等。而 std::cerr 则常用于报告错误、警告和异常情况,以便能够及时注意和处理程序中的问题。

由于 std::cerr 是一个非缓冲的流,并且将其输出视为错误信息,因此在编写调试代码和处理异常时,使用 std::cerr 可以获得更及时和准确的错误报告,以便于调试和追踪问题。而 std::cout 则适合用于一般的输出和日志记录。

需要注意的是,std::coutstd::cerr 都是流对象,可以像其他流一样使用流操作符(<<)来输出数据。例如:

#include <iostream>

int main() {
    int value = 42;
    std::cout << "Value: " << value << std::endl; // 正常输出
    std::cerr << "Error: Something went wrong!" << std::endl; // 错误输出
    return 0;
}

在使用时,根据你的需求选择适当的输出流对象。-end

● 基于绑定 (tie) 的同步

– 流可以绑定到一个输出流上,这样在每次输入 / 输出前可以刷新输出流的缓冲区
– 比如: cin 绑定到了 cout 上,所以输入之前的输出 都会打印出来

● 与 C 语言标准 IO 库的同步

– 缺省情况下, C++ 的输入输出操作会与 C 的输入输出函数同步

可以通过 sync_with_stdio 关闭该同步

本章大量参考了:cppreference 中流相关的内容。

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

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

相关文章

机器学习笔记 - 基于TensorRT或CUDA推理第一次速度慢的解决方案参考

一、简述 不管是基于CUDA还是基于TensorRT进行模型推理,都是分三个阶段,将数据从内存拷贝到显存,进行推理,将推理结果从显存拷贝到内存。 关于TensorRT推理,可以参考之前的博客。 机器学习笔记 - windows基于TensorRT的UNet推理部署_坐望云起的博客-CSDN博客NVIDIA Tenso…

linux sshd 病毒清理

原因&#xff1a;开启了flink web submit 具体原因不清楚&#xff0c;三个flink集群&#xff0c;只要开了这个就中毒 参考&#xff1a;解决linux中挖矿病毒 Linux系统常见的病毒介绍&#xff08;附解决方案&#xff09; 1、清理定时任务 修改cron 文件时 可能会存在被锁不允…

Cartographer自定义lua参数的方法

Cartographer中, 配置参数大多数都是从lua文件中得到的, 不是像其他的开源框架大多使用xml等文件进行参数配置. 假如我们要配置一个名字是rotation_condition的配置参数在pose_graph_2d.cc中, 想要使用方法为 options_.translation_condition()配置步骤如下: 1. 修改proto文件…

界面控件Telerik UI for WPF R2 2023——拥有全新的Windows 11精简主题

Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序&#xff0c;同时还能快速构建企业级办公WPF应用程序。Telerik UI for WPF支持MVVM、触摸等&#xff0c;创建的应用程序可靠且结构良好&#xff0c;非常容易维护&#xff0c;其直观的API将无缝地集成Visua…

无线视频传输|介绍四款基于wifi模块的视频传输方案

为满足产品物联网升级过程中对更高分辨率的视频源的需求&#xff0c;本篇带大家一起来了解一下支持高清视频传输&#xff0c;能够有效解决现有无线视频传输方案中&#xff0c;传输距离短、延迟大、不稳定等问题的四款视频传输方案&#xff1a;无人机视频传输方案&#xff0c;20…

java.sql.Time 字段时区问题 Mybatis 源码分析

java.sql.Time 字段时区问题 系列文章目录 第一章 初步分析 第二章 Mybatis 源码分析 第三章 Jackson 源码分析 意想不到的Time处理类 文章目录 java.sql.Time 字段时区问题 系列文章目录前言Mybatis源码阅读1. ResultSetImpl部分源码&#xff1a;2. SqlTimeValueFactory部分…

git分支的更新按钮不可用,idea 的git命令无法识别

现象 从git分支签出其本地分支&#xff0c;但是签出之后该分支的更新按钮为灰色&#xff0c;我只能拉取&#xff0c;不能更新&#xff0c;也不能推送 解决 打开idea的终端&#xff0c;执行命令git branch --set-upstream-toorigin/远程上的分支名 。又引出另外一个问题无法识别…

Java阶段四Day09

Java阶段四Day09 文章目录 Java阶段四Day09过滤器创建过滤器过滤器的作用执行过滤器 为什么写配置文件关于登录和认证的区别前端获取用户状态 过滤器 使用JWT取代Session&#xff0c;不管做什么都携带着JWT&#xff0c;那么服务端不管处理什么请求、或绝大多数请求都要尝试获取…

如何让金鸣识别转出来的excel表名不为域名?

我们知道&#xff0c;金鸣表格文字识别系统&#xff08;简称金鸣识别&#xff09;可以将图片转为excel表格&#xff0c;使用起来非常方便&#xff0c;由于它采用了超前AI的技术&#xff0c;且经过深度学习&#xff0c;所以它的识别准确率也非常高&#xff0c;让我们节省了不少人…

基于html+css的图展示137

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

jenkins 自动安装nodejs16.16.0版本报错处理

jenkins 自动安装nodejs16.16.0版本报错了&#xff0c;好像访问不了下面的网址&#xff0c;所以下载不了文件报错 那就人工安装吧&#xff0c;下载16.16.0nodejs版本后&#xff0c;到 在这个目录下安装/root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation …

火车售票管理系统

1、项目概要 2 2、数据库设计 2 2.1 数据表 2 2.2 业务表及其字段 4 3、设计与实现 16 3.1业务功能1名称&#xff1a;系统管理 16 3.1-1 员工管理 16 3.1-2 角色维护 18 3.1-2 操作员管理 19 3.2业务功能2名称&#xff1a;列车管理 21 3.2-1 车辆管理 21 3.2-2 站点管理 23 3.2…

021:vue中watch监听页面变化 动态设置iframe元素的高度

第021个 查看专栏目录: VUE — element UI vue项目中如何动态的设置iframe的高度的呢&#xff0c;这里主要用到了监听的功能&#xff0c;页面高度变化时&#xff0c;设定的动态高度也会相应的改变。 template中&#xff1a; <iframe width"100%" :height"f…

maven使用profile动态配置(IDEA演示)

简介 使用Maven的profile来切换不同环境(开发/测试/发布生产)的配置文件 需求简介 通过把不同环境的配置参数信息,放到不同环境的配置文件里(例如:dev.properties开发环境配置文件).Maven在打包的时候根据选择不同的环境(例如dev:生产环境)调用对应的配置文件(dev.properties)…

FPGA XDMA 中断模式实现 PCIE X8 上位机视频传输 提供工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案图像产生、发送、缓存XDMA简介XDMA中断模式图像读取、输出、显示QT上位机及其源码 5、vivado工程详解6、上板调试验证7、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI Express&#xff09;采…

springboot 国家公务员招聘网站-计算机毕设 附源码80528

springboot 国家公务员招聘网站 目 录 摘要 1 绪论 1.1研究背景与意义 1.2开发现状 1.3系统开发技术的特色 1.4springboot框架介绍 1.5论文结构与章节安排 2 2国家公务员招聘网站系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.3.2数据修改流程 2.…

【(不用Ajax)解决 Layui 插件分页点下一页后又自动跳回前一页的问题】

问题描述: 我们在使用Layui插件进行分页会出现一个常见的问题。就是假如我们不用异步的方法进行分页获取后端的数据时&#xff0c;进行window.location.href进行跳转的进行后端分页。 会遇到: 切换页面的时候&#xff0c;点下一页后又自动跳回前一页的问题 原因:有一个curr属…

论文翻译:2021_Real-Time Denoising and Dereverberation wtih Tiny Recurrent U-Net

论文地址&#xff1a;微型循环U-Net实时降噪和去混响 论文代码&#xff1a; https://github.com/YangangCao/TRUNethttps://github.com/amirpashamobinitehrani/tinyrecurrentunet 引用格式&#xff1a;Choi H S, Park S, Lee J H, et al. Real-Time Denoising and Dereverbera…

将画面上的DOM元素转为SVG并且导出

需求如下&#xff1a; import { elementToSVG } from dom-to-svg; let dom document.querySelector(#pane-${this.currentTabIndex}); const svgDocument elementToSVG(dom); const svgString new XMLSerializer().serializeToString(svgDocument); common.download(this.…

Oracle把单行数据拆分成多行

背景&#xff1a;把接收人[JSRID]拆分为多行&#xff0c;接收人是存在一个字段中&#xff0c;以逗号隔开&#xff0c;每次会议的接收人数量不一 建表语句&#xff1a; CREATE TABLE "HYTZGGZS_HYTZGGXXTJ" ("WF_ORUNID" VARCHAR2(255 BYTE) VISIBLE,&quo…