C++证道之路第十七章输入输出和文件

news2024/12/27 12:01:34

一、C++输入和输出概述

C++ 提供了丰富的输入/输出(I/O)功能,这些功能主要通过 <iostream> 头文件中的类和对象来实现。

1.流和缓冲区

C++把程序输入和输出看作字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出的流中。

管理输入包含两步:

①将流与输入去向的程序关联起来。

②将流与文件关联起来。

通常、通过使用缓冲区可以更高效的处理输入和输出。缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序需传输到设备的临时储存工具。通常,像磁盘驱动器这样的设备以512字节或更多的块为单位来传输信息,而程序通常每次只能处理一个字节的信息。缓冲区帮助匹配这两种不同的信息传递速率。

这种原理与水库在暴风雨中收集几兆加仑的流量的水,然后以比较文明的速度给你家里供水时一样的。输出时,程序首先填满缓冲区,然后把整块数据传输给硬盘,并清空缓冲区,以备下一批输出是好用。这被称为刷新缓冲区。

2、流、缓冲区和iostream文件

管理流和缓冲区的工作有点复杂,但iostream文件中包含一些专门设计用来实现管理流和缓冲区的类。

3、重定向

标准输入和输出流通常连接着键盘和屏幕。但很多操作系统(包括unix、Linux、和Windows)都支持重定向,这个工具使得能够改变标准输入和标准输出。

二、使用cout进行输出

1.重载的<<运算符

在C++中,与C一样,<<运算符的默认含义是按位左移运算符。表达式x<<3的意思,将x的二进制表示中所有的位向左移动3位。显然,这与输出的关系不大。但ostream类重新定义了<<运算符,方法是将其重载为输出。在这种情况下,<<叫做插入运算符,而不是左移运算符(左移运算符由于其外观(像向左流动的信息流)而获得这种新角色)。插入运算符被重载,使之能够识别C++中所有的基本类型:

unsigned char;

signed char;

char;

short;

unsigned short;

int;

unsigned int;

long;

unsigned long;

long long;

unsigned long long;

float;

double;

long double;

2.其他ostream方法

除了各种operator<<()函数外,ostream类还提供了put()方法和write()方法,前者用于显示字符,后者用于显示字符串。

3.刷新输出缓冲区

在C++中,输出到控制台(通常是std::cout)或文件时,数据可能不会立即显示在目标位置,而是先被存储在缓冲区中。当缓冲区满或者某些特定条件被满足时,缓冲区的内容才会被刷新(即发送到其目标)。为了控制这种行为,C++提供了一些方法来手动刷新输出缓冲区。

std::endl是一个操纵符,它不仅插入一个换行符(就像'\n'),而且立即刷新输出缓冲区。这是最常用的刷新输出缓冲区的方法。

std::cout << "Hello, World!" << std::endl;

std::flush是一个操纵符,用于立即刷新输出缓冲区,但不插入任何字符。

std::cout << "Hello, World!" << std::flush;
4.用cout进行格式化

在C++中,使用std::cout进行格式化输出是常见的操作,它允许你控制输出的格式、精度、对齐方式等。

控制计数系统:

dec:设置基数为10,即十进制。

hex:设置基数为16,即十六进制。

oct:设置基数为8,即八进制。

std::cout << std::dec << 12 << std::endl; // 十进制输出12  
std::cout << std::hex << 12 << std::endl; // 十六进制输出C  
std::cout << std::oct << 12 << std::endl; // 八进制输出14

设置字段宽度:
 

std::setw(int n):设置下一个输出项的宽度为n个字符。如果输出项的长度小于n,则会在左侧(或右侧,取决于对齐方式)填充空格。

std::cout << std::setw(5) << 12 << std::endl; // 输出"   12"(宽度为5,右对齐)

对齐方式:

std::left:左对齐输出

std::right:右对齐输出(默认)

std::internal:在符号和数字之间填充空格(通常用于浮点数)

std::cout << std::left << std::setw(5) << 12 << std::endl; // 左对齐输出"12   "  
std::cout << std::right << std::setw(5) << 12 << std::endl; // 右对齐输出"   12"

设置填充字符:

std::setfill(char c):设置用于填充的字符

std::cout << std::setfill('*') << std::setw(5) << 12 << std::endl; // 输出"*12**"

设置浮点数的显示精度:

std::setprecision(int n):设置浮点数的精度为n位有效数字

std::cout << std::setprecision(2) << 3.14159 << std::endl; // 输出"3.1"

显示0和末尾的小数点:
std::cout.setf(std::ios_base::showpoint):强制显示小数点,即使它后面没有数字

std::cout.setf(std::ios_base::fixed):使用固定的小数点表示法,而不是科学记数法

std::cout << std::setprecision(2) << std::fixed << 3.0 << std::endl; // 输出"3.00"

三、使用cin进行输入

cin解释输入的方式取决于输入的数据类型。istream类(在iostream头文件中定义)重载了抽取运算符>>,使之能够识别下面这些基本类型:

signed char&

unsigned char &

char &

short &

unsigned short &

int &

unsigned int &

long &

unsigned long &

long long &

unsigned long long &

float &

double &

long double &

1.cin>>如何检查输入

检查流的状态:

可以通过检查std::cin的状态来查看输入是否成功。通常,我们关心两个状态标志:eofbit(表示已经到达文件末尾)和failbit(表示输入失败,通常是因为输入的数据类型与期望的不符)。

int num;  
if (std::cin >> num) {  
    // 输入成功  
    std::cout << "Input was successful: " << num << std::endl;  
} else {  
    // 输入失败,可能是非整数输入  
    std::cout << "Input failed!" << std::endl;  
    // 清除错误状态,以便后续输入  
    std::cin.clear();  
    // 忽略错误输入,直到遇到有效的输入  
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  
}

使用std::getline()和字符串解析:

可以使用std::getline来读取一行,然后尝试将其解析为你想要的数据类型。

std::string input;  
std::getline(std::cin, input);  

std::istringstream iss(input);  
int num;  
if (iss >> num) {  
    // 输入成功  
    std::cout << "Input was successful: " << num << std::endl;  
} else {  
    // 输入失败,可能包含非整数字符  
    std::cout << "Input failed!" << std::endl;  
}

使用异常处理:

std::cin本身不会抛出异常,但你可以使用自定义函数或包装器来在输入失败时抛出异常。

使用第三方库:

有些第三方库提供了更强大和灵活的输入验证和解析功能,例如Boost.Spirit。

2.流状态

在C++中,与流状态相关的知识点主要涉及std::istream(例如std::cin)和std::ostream(例如std::cout)对象的状态标志。这些状态标志用于指示流的状态,如是否成功读取或写入数据,是否遇到文件结束,或者是否发生错误。

状态标志:

eofbit:End-Of-File bit。当到达输入流的末尾时设置。

failbit:Fail bit。当输入/输出操作失败时设置,例如尝试从流中读取一个非数字的字符到int变量时

badbit:Bad bit。当发生严重错误时设置,如内存不足或无效流操作

goodbit:Good bit。当没有设置上述任何错误标志时设置。它是流状态的正常状态

检查流状态:

使用clear()成员函数可以重置流的状态标志。例如,cin.clear()将清除cin对象的所有错误标志

忽略输入:

如果输入流中有错误的输入,你可能想要忽略它并继续读取。可以使用ignore()成员函数来跳过字符,直到遇到特定的字符(默认为换行符)或读取了指定数量的字符

异常处理:

默认情况下,C++标准库流不会抛出异常来报告错误。但是,你可以通过设置流的异常掩码来更改此行为。例如,使用exceptions()成员函数可以设置当发生特定错误时流应抛出异常

错误处理:

当检测到输入错误时,通常的做法是清除错误状态,忽略错误的输入,并提示用户重新输入

流缓冲区:

流通常与缓冲区关联,该缓冲区用于存储待写入或待读取的数据。了解缓冲区如何工作以及何时刷新它们对于理解和处理流错误很重要

同步流:

在某些情况下,你可能希望将多个流(如std::cinstd::cout)同步,以确保它们按照预期的顺序进行读取和写入。可以使用std::ios_base::sync_with_stdio函数来实现这一点

流操纵器:

操纵器是用于修改流状态的特殊函数或对象。例如,std::endl不仅插入一个换行符,还刷新输出流。其他操纵器(如std::decstd::hexstd::setwstd::setfill等)用于格式化输出

文件流:

与标准输入/输出流类似,文件流(如std::ifstreamstd::ofstream)也有状态标志,并且可以使用相同的方法来检查、修改和处理这些状态

3.其他istream类方法

略,没意思

4.其他istream方法

略,没意思

四、文件输入和输出

C++I/O类软件包处理文件输入和输出的方式与处理标准输入和输出的方式非常相似。要写入文件,需要创建一个ofstream对象,并使用ostream方法。

1.简单的文件I/O

要让程序写入文件,必须这样做:
创建一个ofstream对象来管理输出流;

将该对象与特定的文件关联起来;

以使用cout的方式使用该对象,唯一的区别是输出将进入文件,而不是屏幕。

警告:以默认模式打开文件进行输出将自动把文件的长度截短为零,这相当于删除已有的内容。

读取文件的要求与写入文件相似:
创建一个ifstream对象来管理输入流;

将该对象与特定的文件关联起来;

以使用cin的方式使用该对象。

2.流状态检查和is_open()

.isopen()检查文件是否打开。

3.打开多个文件

如果需要同时打开两个文件,则必须为每个文件创建一个流。

注意:有些C++实现要求在该程序末尾使用fin.clear(),有些则不要求,这取决于将文件与ifstream对象关联起来时,是否自动重置流状态。使用fin.clear()是无害的,即使在不必使用它的时候使用。

4.命令行处理技术
wc report1 report2 report3

其中,WC是程序名,report1,report2,report3是作为命令行参数传递给程序的文件名。

注意:有些C++实现要求在该程序末尾使用fin.clear(),有些则不要求,这取决于将文件与ifstream对象关联起来时,是否自动重置流状态。使用fin.clear()是无害的,即使在不必使用它的时候使用。

5.文件模式

文件模式描述的是文件将被如何使用:读写,追加等。将流与文件关联时(无论是使用文件名初始化文件流对象,还是还是使用open()方法,都可以提供指定文件模式的第二个参数)

6.随机存取

随机存取指的是直接移动(不是依此移动)到文件的任何位置。随机存取常被用于数据库文件,程序维护一个独立的索引文件,该文件指出数据在主数据文件中的位置。这样,程序便可以直接跳到这个位置,读取(还可能修改)其中数据。

五、内核格式化

不说了,无聊

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

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

相关文章

使用 FFmpeg 从音视频中提取音频

有时候我们需要从视频文件中提取音频&#xff0c;并保存为一个单独的音频文件&#xff0c;我们可以借助 FFmpeg 来完成这个工作。 一、提取音频&#xff0c;保存为 mp3 文件: 要使用 FFmpeg 从音视频文件中提取音频&#xff0c;并将 ACC 编码的音频转换为 MP3 格式&#xff0…

【数据结构(邓俊辉)学习笔记】列表02——无序列表

文章目录 0.概述1.插入与构造1.1 插入1.1.1 前插入1.1.2后插入1.1.3 复杂度 1.2 基于复制构造1.2.1 copyNodes()1.2.2 基于复制构造1.2.3 复杂度 2.删除与析构2.1 删除2.1.1 实现2.1.2 复杂度 2.2 析构2.2.1 释放资源及清除节点2.2.2 复杂度 3.查找3.1 实现3.2 复杂度 4.唯一化…

FFmpeg学习记录(四)——SDL音视频渲染实战

1.SDL使用的基本步骤 SDL Init/sDL _Quit()SDL_CreateWindow()/SDL_DestoryWindow()SDL CreateRender() SDL_Windows *windows NULL;SDL_Init(SDL_INIT_VIDEO);window SDL_CreateWindow("SDL2 Windows",200,200, 640,480,SDL_WINDOW_SHOWN);if(!window) {printf(&…

【C语言回顾】数据在内存中的存储

前言1. 概述2. 大小端字节序和字节序判断2.1 大端字节序&#xff08;Big-Endian&#xff09;2.2 小端字节序&#xff08;Little-Endian&#xff09;2.3 判断字节序的示例 3. 数据在内存中的存储3.1 整数在内存中的存储3.2 浮点数在内存中的存储 结语 ↓ 上期回顾: 【C语言回顾】…

STM32 01

1、编码环境 1.1 安装keil5 1.2 安装STM32CubeMX 使用STM32CubeMX可以通过界面的方式&#xff0c;快速生成工程文件 安装包可以从官网下载&#xff1a;https://www.st.com/zh/development-tools/stm32cubemx.html#overview 安装完要注意更新一下固件包的位置&#xff0c;因为…

A股上市公司财务松弛数据集(2000-2022年)

01、数据介绍 财务松弛是指企业在运营过程中&#xff0c;由于各种原因导致其财务状况出现一定程度的松弛或宽裕状态。这种状态通常表现为企业持有较多的现金和流动性资产&#xff0c;同时负债相对较少&#xff0c;或者企业有较多的未使用授信额度等。 本数据包括&#xff1a;…

伺服电机初识

目录 一、伺服电机的介绍二、伺服电机的基本原理三、伺服电机的技术特点四、伺服电机的分类五、实际产品介绍1、基本技术规格&#xff1a;2、MD42电机硬件接口3、通讯协议介绍3.1 通讯控制速度运行3.2 通讯控制位置运行3.3 通讯控制转矩运行 4、状态灯与报警信息 一、伺服电机的…

C语言之整形提升和算术转换

目录 前言 一、整形提升 二、算术转换 总结 前言 本文主要介绍C语言中的整形提升和算术转换的概念和意义&#xff0c;以及例题帮助理解&#xff0c;了解之后&#xff0c;我们就能知道在C语言中&#xff0c;字符型变量如何计算以及如果变量的类型、字节大小不一致的情况下&am…

JVM组成之类加载器

类加载器&#xff08;ClassLoader&#xff09;&#xff1a;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。 类加载器多数是有Java编写的&#xff0c;也有部分是c编写的&#xff0c;负责接收来自外部的二进制数据&#xff0c;然后执行JNI&#xff08;也就是本…

2010NOIP普及组真题 2. 接水问题

线上OJ&#xff1a; 一本通&#xff1a;http://ybt.ssoier.cn:8088/problem_show.php?pid1950 解法一、朴素模拟 核心思想&#xff1a; 朴素模拟&#xff1a; 1、先给每个b[i]水龙头分配一个人a[i]&#xff0c;b[i] 表示水龙头的剩余时间。同时标记该水龙头为 used 使用中 2…

(论文阅读-优化器)A Cost Model for SPARK SQL

目录 Abstract 1 Introduction 2 Related Work 3 Background and Spark Basics 4 Cost Model Basic Bricks 4.1 Cluster Abastraction and Cost Model Parameters 4.2 Read 4.3 Write 4.4 Shuffle Read 4.5 Broadcast 5 Modeling GPSJ Queries 5.1 Statistics and S…

交互中的“互”难以产生的原因

脑机交互技术的目标是通过分析和解读大脑活动&#xff0c;将其与特定的意图、指令或行为连接起来。通过训练和分析&#xff0c;可以建立起大脑活动与特定行为或意图之间的关联模型&#xff0c;从而实现脑机交互的应用&#xff0c;例如控制外部设备、传递信息等。然而&#xff0…

视频教程下载:为 GPTs 商店构建 10 个 GPTs获得被动收入

欢迎来到 AI 驱动的内容创作新时代 - GPT 商店。这门综合课程是您成为定制和利用 GPT 模型解决多样化应用的专家的路线图。无论你是错过了应用商店革命的初始浪潮还是乘着它取得了成功&#xff0c;这都是你站在下一个重大数字飞跃前沿的机会。 课程模块&#xff1a; - 介绍 Ch…

抓包证书安装到安卓7.0+手机

前言: 首先理解一下,这个不只是证书到浏览器,而是抓包证书到安卓7.0+手机上的文章; 还有一点区分,在浏览器上装的证书,只是让抓包工具可以抓取手机浏览器的包,而不是抓取手机app上的包; 如果你的证书只是简单的在浏览器下进行安装,那么你的手机app是走不了代理网络的…

iOS - Undefined symbols: 解决方法

Undefined symbols: 是让人苦恼的报错&#xff0c;如何知道是 哪个 symbols 不对呢&#xff1f; 今天探索到下面的方法&#xff1a; 1、点击导航上方 最右侧的按钮&#xff0c;查看历史报错 2、选中报错信息&#xff0c;右键选择 Expand All Transcripts 在出现的详细信息面…

【Redis】Redis命令(一)

1.基本命令 1.1.切换DB 默认使用的是 0 号 DB&#xff0c;可以通过 select db 索引来切换 DB 1.2.查看 key 数量 dbsize 命令可以查看当前数据库中 key 的数量 1.3.删除当前库中数据 flushdb 命令仅仅删除的是当前数据库中的数据&#xff0c;不影响其它库 1.4.删除所有库中数据…

Spring Cloud架构进化实操:Eureka、Apollo、OpenFeign、Ribbon、Zuul组件

文章目录 前言一、引出二、服务注册与发现2.1 创建Eureka注册中心2.1.1 引入pom依赖2.1.2 配置yaml2.1.3 启动服务21.4 测试访问 2.2 创建服务提供者2.2.1 配置yaml2.2.2 启动服务2.2.3 测试访问 2.3 创建服务消费者2.3.1 服务提供者接口2.3.2 服务消费者调用接口 三、负载均衡…

如何高速下载,百度 阿里 天翼 等网盘内的内容

如何高速下载&#xff0c;百度 阿里 天翼 等网盘内的内容&#x1f3c5; 前言教程下期更新预报&#x1f3c5; 前言 近段时间经常给大家分享各种视频教程&#xff0c;由于分享的资料是用迅雷网盘存的&#xff0c;但是绝大部分用户都是使用的某度&#xff0c;阿某的这些网盘&…

OpenCV如何使用 GDAL 读取地理空间栅格文件(72)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV的周期性噪声去除滤波器(70) 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目录 目标 代码&#xff1a; 解释&#xff1a; 如何使用 GDAL 读取栅格数据 注意 …

DS:顺序表、单链表的相关OJ题训练(1)

欢迎各位来到 Harper.Lee 的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦&#xff01; 在DS&#xff1a;单链表的实现 和 DS&#xff1a;顺序表的实现这两篇文章中&#xff0c;我详细介绍了顺序表和单链表的…