(七)C++的异常和文件输入与输出

在C++中,**异常(Exception)**是一种用于处理程序运行过程中可能出现的错误或异常情况的机制。异常机制允许程序在检测到错误时抛出(throw)一个异常,并在适当的位置捕获(catch)并处理该异常,从而提高程序的健壮性和可维护性。以下是对C++异常处理的详细介绍,包括其定义、语法、实现方式、常见异常类型以及最佳实践。

一.异常

异常是程序在运行时检测到的错误或异常情况。异常处理机制允许程序在检测到错误时中断正常的控制流,抛出异常,并在调用栈中向上传递,直到找到适当的异常处理器来处理该异常。

语法
C++的异常处理主要通过以下三个关键字实现:
try:定义一个可能抛出异常的代码块。
throw:抛出一个异常。
catch:捕获并处理异常。

实现方式
a. 基本异常处理

#include <iostream>
#include <stdexcept>void divide(int a, int b) {if(b == 0) {throw std::invalid_argument("Division by zero");}std::cout << "Result: " << (a / b) << std::endl;
}int main() {try {divide(10, 2); // 正常执行divide(10, 0); // 抛出异常} catch (const std::invalid_argument& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

b. 自定义异常类
可以创建自定义的异常类,以提供更具体的错误信息或行为。

#include <iostream>
#include <exception>class MyException : public std::exception {
private:std::string message;
public:MyException(const std::string& msg) : message(msg) {}virtual const char* what() const noexcept override {return message.c_str();}
};void doSomething(int value) {if(value < 0) {throw MyException("Value is negative");}std::cout << "Value is valid: " << value << std::endl;
}int main() {try {doSomething(5);  // 正常执行doSomething(-3); // 抛出自定义异常} catch (const MyException& e) {std::cout << "Caught MyException: " << e.what() << std::endl;} catch (const std::exception& e) {std::cout << "Caught std::exception: " << e.what() << std::endl;}return 0;
}

常见异常类型
C++标准库提供了一些常用的异常类型,主要定义在头文件中:
std::exception:所有标准异常的基类。
std::runtime_error:运行时错误异常。
std::invalid_argument:无效参数异常。
std::out_of_range:超出范围异常。
std::overflow_error:溢出错误异常。
std::underflow_error:下溢错误异常。

最佳实践
a. 使用异常捕获的顺序
捕获异常的顺序应从具体到一般,避免先捕获一般异常,再捕获具体异常,否则具体异常将无法被捕获。

错误示例:
try {// 可能抛出异常的代码
} catch (const std::exception& e) {// 捕获所有标准异常
} catch (const MyException& e) {// 永远不会被捕获
}正确示例:
try {// 可能抛出异常的代码
} catch (const MyException& e) {// 捕获自定义异常
} catch (const std::exception& e) {// 捕获其他标准异常
}

b. 避免过度使用异常
异常应仅用于处理真正的错误情况,而不是用于控制程序流程。过度使用异常可能导致代码难以理解和维护。

c. 资源管理
在抛出异常时,确保正确管理资源,避免资源泄漏。可以使用RAII(资源获取即初始化)惯用法或智能指针来管理资源。

#include <iostream>
#include <stdexcept>
#include <memory>class Resource {
public:void use() {// 使用资源的代码}~Resource() {// 释放资源的代码}
};void process() {std::unique_ptr<Resource> res = std::make_unique<Resource>();res->use();throw std::runtime_error("An error occurred");
}int main() {try {process();} catch (const std::exception& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

d. 异常安全
编写异常安全的代码,确保在异常抛出时,程序处于一个有效和一致的状态。可以使用noexcept关键字来声明函数不会抛出异常,提高代码的性能和安全性。

二.文件输入与输出

在C++中,文件输入和输出(File I/O) 是通过标准库中的fstream库实现的。fstream提供了三个主要的类用于处理文件操作:
std::ifstream:用于从文件读取数据(输入文件流)。
std::ofstream:用于向文件写入数据(输出文件流)。
std::fstream:可以同时进行读取和写入操作(输入/输出文件流)。
以下是对C++文件输入和输出的详细介绍,包括如何打开和关闭文件、读取和写入数据、处理错误以及一些示例。

读取文件
使用std::ifstream进行文件读取。以下是一些常见的读取方法:
a. 逐行读取

#include <iostream>
#include <fstream>
#include <string>int main() {std::ifstream inputFile("input.txt");if(!inputFile) {std::cerr << "无法打开文件进行读取" << std::endl;return 1;}std::string line;while(std::getline(inputFile, line)) {std::cout << line << std::endl;}inputFile.close();return 0;
}

b. 逐词读取

#include <iostream>
#include <fstream>
#include <string>int main() {std::ifstream inputFile("input.txt");if(!inputFile) {std::cerr << "无法打开文件进行读取" << std::endl;return 1;}std::string word;while(inputFile >> word) {std::cout << word << std::endl;}inputFile.close();return 0;
}

c. 读取二进制文件

#include <iostream>
#include <fstream>int main() {std::ifstream inputFile("data.bin", std::ios::binary);if(!inputFile) {std::cerr << "无法打开文件进行读取" << std::endl;return 1;}char buffer[100];inputFile.read(buffer, sizeof(buffer));std::cout << "读取的字节数: " << inputFile.gcount() << std::endl;inputFile.close();return 0;
}

写入文件
使用std::ofstream进行文件写入。以下是一些常见的写入方法:
a. 写入文本数据

#include <iostream>
#include <fstream>
#include <string>int main() {std::ofstream outputFile("output.txt");if(!outputFile) {std::cerr << "无法打开文件进行写入" << std::endl;return 1;}outputFile << "Hello, World!" << std::endl;outputFile << 123 << std::endl;outputFile.close();return 0;
}

b. 写入二进制数据

#include <iostream>
#include <fstream>int main() {std::ofstream outputFile("data.bin", std::ios::binary);if(!outputFile) {std::cerr << "无法打开文件进行写入" << std::endl;return 1;}char data[] = {0x01, 0x02, 0x03, 0x04};outputFile.write(data, sizeof(data));outputFile.close();return 0;
}

使用std::fstream进行读写
std::fstream允许同时进行读取和写入操作。

#include <iostream>
#include <fstream>
#include <string>int main() {std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::app);if(!file) {std::cerr << "无法打开文件" << std::endl;return 1;}// 写入数据file << "Hello, World!" << std::endl;// 移动文件指针到文件开头file.seekg(0);// 读取数据std::string line;while(std::getline(file, line)) {std::cout << line << std::endl;}file.close();return 0;
}

错误处理
在进行文件操作时,务必检查文件是否成功打开

std::ifstream inputFile("input.txt");
if(!inputFile) {std::cerr << "无法打开文件进行读取" << std::endl;return 1;
}

示例:复制文件内容
以下是一个简单的示例,演示如何将一个文件的内容复制到另一个文件中:

#include <iostream>
#include <fstream>
#include <string>int main() {std::ifstream inputFile("input.txt", std::ios::binary);if(!inputFile) {std::cerr << "无法打开输入文件" << std::endl;return 1;}std::ofstream outputFile("output.txt", std::ios::binary);if(!outputFile) {std::cerr << "无法打开输出文件" << std::endl;return 1;}char buffer[1024];while(!inputFile.eof()) {inputFile.read(buffer, sizeof(buffer));outputFile.write(buffer, inputFile.gcount());}inputFile.close();outputFile.close();return 0;
}

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

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

相关文章

C语言基础学习之环境准备

写在前面 本文看下如何在win环境中使用vs code开发C程序。 1&#xff1a;安装gcc 从这里下载&#xff0c;解压&#xff0c;配置环境变量&#xff0c;执行gcc -v验证: C:\Windows\system32>gcc -v Using built-in specs. COLLECT_GCCgcc COLLECT_LTO_WRAPPERD:/programs/…

LabVIEW之TDMS文件

在很多场合&#xff0c;早期的LabVIEW版本不得不借助常规的数据库来做一些数据管理工作&#xff0c;但常规数据库对于中高速数据采集显然是不合适的&#xff0c;因为高速数据采集的数据量非常大&#xff0c;用一般的数据库无法满足存储数据的要求。 直到TDM(Technical Data Ma…

设置IDEA的内存大小,让IDEA更流畅: 建议设置在 2048 MB 及以上

文章目录 引言I 更改内存设置基于窗口界面进行内存设置修改内存配置文件II IDEA中的一些常见问题及其解决方案引言 方式一:基于窗口界面进行内存设置方式二:修改内存配置文件I 更改内存设置 基于窗口界面进行内存设置 打开IDEA,上方菜单栏 Help > Change Memory Settin…

攻防世界ctf

1.题目名称-文件包含 if(isset($_GET[filename])){$filename $_GET[filename];include($filename);} 通过代码审计&#xff0c;我们发现这存在文件包含漏洞&#xff0c;由于没有很好的进行过滤&#xff0c;所以我们可以通过 URL 参数传递任意文件路径给参数$filename&#…

多线程操作

一.多线程 1.线程的创建 1.继承Thread类,重写run()方法创建线程 2.实现Runnable接口,重写run()方法 3.匿名内部类创建线程 4.匿名内部类实现Runnable接口创建线程 5.[常用]lambda表达式创建线程 2.启动线程 Thread类使用start方法,启动一个线程,对于同一个Thread对象只能…

根文件系统 Debian10【1】移植

1.开发背景 一般根文件系统使用 Busybox 或者是 Buildroot 构建&#xff0c;这样构建出来的文件系统比较小&#xff0c;但是不具备上网功能&#xff0c;扩展性比较差。随着 ARM 的日益强大&#xff0c;ARM 可以搭载更庞大复杂的系统&#xff0c;可以是 Ubuntu 或者 Debian 等发…

OpenSIPS-Dispatcher模块详解:优化SIP流量分发的利器

在 OpenSIPS 中&#xff0c;dispatcher 模块用于实现负载均衡和故障转移。通过 dispatcher 模块&#xff0c;你可以将 SIP 请求分发到一组后端服务器&#xff08;如媒体服务器、代理服务器等&#xff09;&#xff0c;并根据配置的算法和策略动态调整分发逻辑。 模块功能使用样…

09vue3实战-----引入element-plus组件库中的图标

09vue3实战-----引入element-plus组件库中的图标 1.安装2.引入3.优化 element-plus中的icon图标组件的使用和其他平台组件(如el-button按钮)是不一样的。 1.安装 npm install element-plus/icons-vue2.引入 在这我们只讲述最方便的一种引入方法------完整引入。这需要从elem…

Docker 部署 GitLab

一、下载镜像 docker pull gitlab/gitlab-ce 二、运行容器 docker run -d --name gitlab-20080 \n -p 20443:443 -p 20080:80 -p 20022:22 \n -v /wwwroot/opt/docker/gitlab-20080/etc:/etc/gitlab \n -v /wwwroot/opt/docker/gitlab-20080/log:/var/log/gitlab \n -v /www…

优惠券平台(十七):实现用户查询/取消优惠券预约提醒功能

业务背景 当用户预约了一个或多个优惠券抢购提醒后&#xff0c;如果不再需要提醒&#xff0c;可以取消预约通知。不过&#xff0c;虽然用户可以取消提醒&#xff0c;但已经发送到 MQ 的消息不会被撤回&#xff0c;消费者在时间点到达时依然会收到消息。此时&#xff0c;我们不…

【个人开发】macbook m1 Lora微调qwen大模型

本项目参考网上各类教程整理而成&#xff0c;为个人学习记录。 项目github源码地址&#xff1a;Lora微调大模型 项目中微调模型为&#xff1a;qwen/Qwen1.5-4B-Chat。 去年新发布的Qwen/Qwen2.5-3B-Instruct同样也适用。 微调步骤 step0: 环境准备 conda create --name fin…

深入理解进程优先级

目录 引言 一、进程优先级基础 1.1 什么是进程优先级&#xff1f; 1.2 优先级与系统性能 二、查看进程信息 2.1 使用ps -l命令 2.2 PRI与NI的数学关系 三、深入理解Nice值 3.1 Nice值的特点 3.2 调整优先级实践 四、进程特性全景图 五、优化实践建议 结语 引言 在操…

大数据学习之SparkSql

95.SPARKSQL_简介 网址&#xff1a; https://spark.apache.org/sql/ Spark SQL 是 Spark 的一个模块&#xff0c;用于处理 结构化的数据 。 SparkSQL 特点 1 易整合 无缝的整合了 SQL 查询和 Spark 编程&#xff0c;随时用 SQL 或 DataFrame API 处理结构化数据。并且支…

k8s的操作指令和yaml文件

一、项目的生命周期 创建----》发布----》更新----》回滚----》删除 1.创建 kubectl create deployment nginx1 --imagenginx:1.22 --replicas3 #基于deployment控制器创建pod&#xff0c;控制器的名称是nginx1,pod使用的镜像是nginx:1.22&#xff0c;pod的数量有3个 2.发布 ku…

解锁 DeepSeek 模型高效部署密码:蓝耘平台全解析

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

k8s部署rabbitmq

1. 创建provisioner制备器&#xff08;如果已存在&#xff0c;则不需要&#xff09; 1.1 编写nfs-provisioner-rbac.yaml配置文件 apiVersion: v1 kind: ServiceAccount metadata:name: nfs-client-provisionernamespace: wms --- kind: ClusterRole apiVersion: rbac.author…

评估大模型(LLM)摘要生成能力:方法、挑战与策略

大语言模型&#xff08;LLMs&#xff09;有着强大的摘要生成能力&#xff0c;为信息快速提取和处理提供了便利。从新闻文章的快速概览到学术文献的要点提炼&#xff0c;LLMs 生成的摘要广泛应用于各个场景。然而&#xff0c;准确评估这些摘要的质量却颇具挑战。如何确定一个摘要…

dmd-50

dmd-50 一、查壳 无壳&#xff0c;64位 二、IDA分析 main 下面的内容中数据经过R键转换&#xff0c;你就会知道v41的内容&#xff0c;以及是当v41成立时key是有效的。 v41870438d5b6e29db0898bc4f0225935c0 结合上面的函数知道&#xff1a;v41经过MD5解密后是key 注意是…

关于图像锐化的一份介绍

在这篇文章中&#xff0c;我将介绍有关图像锐化有关的知识&#xff0c;具体包括锐化的简单介绍、一阶锐化与二阶锐化等方面内容。 一、锐化 1.1 概念 锐化&#xff08;sharpening&#xff09;就是指将图象中灰度差增大的方法&#xff0c;一次来增强物体的轮廓与边缘。因为发…

全程Kali linux---CTFshow misc入门(38-50)

第三十八题&#xff1a; ctfshow{48b722b570c603ef58cc0b83bbf7680d} 第三十九题&#xff1a; 37换成1&#xff0c;36换成0&#xff0c;就得到长度为287的二进制字符串&#xff0c;因为不能被8整除所以&#xff0c;考虑每7位转换一个字符&#xff0c;得到flag。 ctfshow{5281…