《C++ Primer(第5版)》学习笔记(第5章)

2023-11-19

第5章 语句

C++提供了条件执行语句、循环语句和用于中断当前控制流的跳转语句,本章将具体介绍这些语句。

5.1 简单语句

空语句

最简单的语句是空语句,只有一个单独的分号。如在程序的某个地方语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。

// 读取输入流的内容直到遇到一个特定值
while (cin >> s && s != sought)
	; // 空语句,循环的全部工作在条件部分就可以完成
复合语句

用花括号括起来的语句和声明的序列,也称作块,一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。

5.2 语句作用域

可在if、switch、while和for语句的控制结构内定义变量,定义在控制结构中的变量只在语句相应的块内部可见,一旦语句结束,变量就超出其作用范围了。

for (int i = 0; i <= n; ++i) // 在for语句内部定义i,只能在for对应的块中使用
	cout << i << endl;
i = 0;                       // 错误:在循环外部不能使用

5.3 条件语句

5.3.1 if 语句

if (condition1)  // condition1类型必须能转换成布尔类型
	statement1; 
	// condition1为真:执行statement1,执行完后执行后面的其他语句,跳过else if和else语句
else if (condition2)
	statement2; 
	// condition1为假,condition2为真:跳过statement1,执行statement2,执行完后跳过else语句
else
	statement3; 
	// condition1和condition2为假:跳过statement1和statement2,执行statement3

当statement中有多条语句想要一起执行时,要使用花括号{}将其括住。

当一个if语句嵌套在另一个if语句内部时,很可能if分支会多于else分支,C++规定else与离它最近的尚未匹配的if匹配。

5.3.2 switch 语句

switch (expression) { // 对表达式求值,然后与每个case标签比较
	case val1:        // 匹配成功则执行statement1,不成功则匹配val2
		statement1;
		break;        // 遇到break后跳出switch语句
	case val2:
		statement2;
		break;
	case val3:
		statement3;
		break;
	default:          // 该语句可省略
		statement4;
		break;
// 若所有case标签都未匹配成功则执行紧跟在default标签后的语句
}

如果某个case标签匹配成功,将从该标签开始往后顺序执行所有case、default分支(不管后面的case标签有没有匹配上),除非中断这一过程(如break)。

switch的执行过程可能会跨过某些case标签,如果程序跳转到了某个特定的case,则switch结构中该case标签之前的部分会被忽略掉。如果在某处一个带有初值的变量位于作用域之外,在另一处该变量位于作用域之内,则从前一处跳转到后一处是非法行为。

5.4 迭代语句

5.4.1 while 语句

当不确定到底要迭代多少次,或者在循环结束后想访问循环控制变量的可以用while循环。

while (condition)
	statement

while语句的执行过程是交替地检测condition和执行statement,直至condition为假为止。condition可以是一个表达式或者一个带初始化的变量声明。应该由条件本身或者是循环体设法改变condition的值,否则循环可能无法终止。

定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程。

5.4.2 传统的 for 语句

for (init-statement; condition; expression)
	statement

for循环的执行过程如下:

Created with Raphaël 2.2.0 init-statement condition statement expression quit yes no

init-statement必须是以下三种形式中的一种:声明语句、表达式语句或者空语句,可以定义多个对象,但是只能有一条声明语句,因此所有变量的基础类型必须相同。

for 语句头能省略掉init-statement、condition和expression中的任何一个(或者全部)

5.4.3 范围 for 语句

for (declaration: expression)
	statement

expression表示的必须是一个序列,如用花括号括起来的初始值列表、数组或者vector或string等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员。

declaration定义一个变量,序列中每个元素都能转换成该变量的类型。为确保类型相容,可使用auto类型说明符。如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型。

每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行statement。

vector<int> v = {0, 1, 2, 3, 4, 5};
// 范围变量必须是引用类型,这样才能执行写操作
for (auto &r : v)
	r *= 2;

以上范围for语句等价于:

for (auto beg = v. begin(), end = v.end(); beg != end; ++beg) {
	auto &r = *beg;
	r *= 2;
}

5.4.4 do while 语句

do
	statement
while (condition);

do while语句与while语句的区别是:do while语句先执行循环体statement,再检查条件condition,如果condition为假,循环终止,否则,重复循环过程。

condition使用的变量必须定义在循环体之外。

5.5 跳转语句

5.5.1 break 语句

break语句负责终止离它最近的while、do while、for或switch语句,并从这些语句之后的第一条语句开始继续执行。break语句只能出现在迭代语句或者switch语句内部(包括嵌套在此类循环里的语句或块的内部)。

5.5.2 continue 语句

continue语句负责终止离它最近的while、do while、for语句的当前迭代,并立即开始下一次迭代。continue语句只能出现在迭代语句while、do while、for内部(包括嵌套在此类循环里的语句或块的内部)。

对while或do while语句:继续判断条件的值;对于传统for循环:继续执行for语句头的expression;对于范围for语句:用序列中的下一个元素初始化循环控制变量。

5.5.3 goto 语句

goto 语句的作用是从goto语句无条件跳转到同一函数内的另一条语句。其形式为:

goto label; // label是标识一条语句的标识符

用标识符+冒号的形式写带标签的语句:

label: statement; // 可作为goto的目标

goto语句和控制权转向的那条带标签的语句必须位于同一个函数内,goto语句不能将程序的控制权从变量的作用域之外转移到作用域之内。

不要使用goto语句,因为它令程序很难理解且难修改。

5.6 try 语句块和异常处理

5.6.1 throw 表达式

int x, y;
cin >> x >> y;
if (y != 0) {
	cout << x / y << endl;
	return 0;
}
else {
	cerr << "y must be not equal to zero" << endl;
	return -1;
}

上述程序计算两个整数的除法运算,但在真实程序中,应把对象相除的代码和用户交互的代码分离开来。因此改写程序使得检查完成后抛出一个异常:

if (y == 0)
	throw runtime_error("y must be not equal to zero")
cout << x / y << endl;

如果y等于0,就抛出一个异常,该异常是类型runtime_error的对象。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码。

5.6.2 try 语句块

try {
	program-statement 
	// 包括声明在内的任意语句,在语句块内部声明的变量无法在外部访问
}
catch (expression-declaration) { 
	handler-statements
}
catch (expression-declaration) {
	handler-statements
} // ...

5.6.1中的代码用try语句块编写:

while (cin >> x >> y) {
	try { // try语句块是程序本来要执行的任务
		if (y == 0)
		throw runtime_error("y must be not equal to zero")
		cout << x / y << endl;
	}
	catch (runtime_error err) { // catch子句负责处理类型为runtime_error的异常
		cout << err.what() // what是runtime_error类的一个成员函数
			 << "\n Try Again? Enter y or n" << endl;
		char c;
		cin >> c;
		if (!cin || c == 'n')
			break;
	}
} 

在复杂系统中,程序遇到抛出异常代码前,其执行路径已经经过了多个try语句块,如当前try语句块被另一个try语句块调用,而当异常被抛出时,首先搜索抛出该异常的函数,若没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找,以此类推。如一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。

5.6.3 标准异常

C++标准库定义了一组类(分别在4个头文件中)用于报告标准库函数遇到的问题:

  • exception:最通用的异常类exception,只报告异常的发生,不提供任何额外的信息。
  • stdexcept:几种常用的异常类。包括之前提到的runtime_error等。
  • new:bad_alloc异常类型。
  • type_info:bad_cast异常类型。

标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。相反:应当使用string对象或者C风格字符串初始化这些类型的对象,但不允许使用默认初始化的方式。

异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char*,该字符串的目的是提供关于异常的一些文本信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《C++ Primer(第5版)》学习笔记(第5章) 的相关文章

  • 将复选框添加到 UniformGrid

    我正在尝试将复选框动态添加到 wpf 中的统一网格中 但看起来网格没有为它们分配足够的空间 所以它们都有点互相重叠 这就是我将它们添加到后面的代码中的方法 foreach string folder in subfolders PathCh
  • 访问私人成员[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 通过将类的私有成员转换为 void 指针 然后转换为结构来访问类的私有成员是否合适 我认为我无权修改包含我需要访问的数据成员的类 如果不道德 我
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • 将布尔参数传递给 SQL Server 存储过程

    我早些时候问过这个问题 我以为我找到了问题所在 但我没有 我在将布尔参数传递给存储过程时遇到问题 这是我的 C 代码 public bool upload false protected void showDate object sende
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐

  • 【Linux】浅谈Linux内核定时器timer_list

    目录 1 平台说明 2 定时器timer list说明 2 1 所在头文件 2 2 结构体 2 3 重要函数说明 2 4 函数API 2 5 使用方法 3 实例 3 1 驱动程序代码 3 2 测试程序代码 3 3 结果 1 平台说明 Lin
  • 【源码篇】基于SpringBoot+thymeleaf图书馆管理系统

    1 系统介绍 系统总体功能介绍 1 分为系统管理员和用户两类用户 2 开放用户注册功能 3 系统管理员拥有用户管理 图书管理 以及用户的借书申请的确定和还书操作 4 用户只能查询图书 并进行借书操作 提出借书申请 每个用户最多借阅8本 即当
  • 2018年AI成败将见分晓;全球经济重心东移,上海料将在2035年超越巴黎

    2017临近结束 我们先来看看对于来年 都有些什么预测 埃森哲预测CES 2018 AI 5G 区块链以及无人车 明年1月9 12日 CES又将在拉斯维加斯举行 每年 咨询巨头埃森哲 Accenture 都会对CES上的技术趋势做出预测 这
  • 100天精通Python(可视化篇)——第91天:Pyecharts绘制各种折线图实战

    文章目录 专栏导读 1 基本流程 2 多条折线图 3 添加最小值最大值平均值 4 竖线提示信息 5 阶梯图 6 平滑曲线折线图 7 面积折线图 8 堆积图 9 双横坐标折线图 专栏导读 本文已收录于 100天精通Python从入门到就业 本
  • Windows Server 2008 R2 下配置AD证书服务器和HTTPS访问的图文教程 DNS+IIS+AD证书服务

    提前配置好虚拟机和客户机的访问 保证能ping通虚拟机 虚拟机和客户机网络的DNS填写为虚拟机的ip地址 接下来配置好DNS服务 配置域名解析服务 这个用于域名解析 不需要域名访问的可以不配置DNS 使用IP访问即可 安装DNS 进入DNS
  • (ros/qt报错) FATAL: ROS_MASTER_URI is not defined in the environment

    安装qt之后 明明打开roscore但是qt运行跟ros有关的节点时报错 FATAL 1450943695 306401842 ROS MASTER URI is not defined in the environment Either
  • 哪些 Java 知识不需要再学了

    张无忌在学太极拳的时候 他爹的师父张三丰告诫他一定要把之前所学习的武功全部忘掉 忘得越多就会学得越快 同样的 自学 Java 的时候一定要先知道哪些 Java 知识不需要再学了 毕竟技术的更新迭代就好像火箭一样快 Java 的一些知识点早已
  • OJ:algorithm头文件中sort函数的应用

    include
  • 【单片机笔记】STM32+ESP8266通过AT指令WIFI连接阿里云MQTT服务器

    上一篇使用USB转串口的方式通过ESP8266wifi模块的方式成功连接上了阿里云 现在就要通过单片机来替换电脑上位机了 这样单片机自动的去调用并发送串口数据更加方便 也更加符合一个产品的开发 板载的传感器有NTC温度 光强 这两个主要用来
  • 100流明相当于多少w_中艺光影秀揭秘一场大型灯光秀究竟要耗费多少电量呢?...

    炫酷的灯光秀 让城市景区的夜色被赋予了无限可能性 现代的灯光秀始于法国里昂 然而 现代技术的飞速发展 现在的灯光秀的技术也是越玩越炫丽 越来越复杂 在大家纷纷对灯光秀表示震撼的同时 也有一些人质疑 举办这么大规模的灯光秀 太 费 电 了 某
  • [Linux打怪升级之路]-文件操作

    前言 作者 小蜗牛向前冲 名言 我可以接受失败 但我不能接受放弃 如果觉的博主的文章还不错的话 还请点赞 收藏 关注 支持博主 如果发现有问题的地方欢迎 大家在评论区指正 目录 一 认识操纵系统下的文件 1 什么是文件 2 文件的类型 3
  • 医疗器械相关展会

    1 CMEF中国国际医疗器械博览会 始创于1979年 每年春秋两届 已成为亚太地区最大的医疗器械及相关产品 服务展览会
  • 机器学习实战项目总结

    1 预测模型新项目模板 机器学习是针对数据进行自动挖掘 找出数据的内在规律 并应用这个规律来预测新数据 一个很好的实践机器学习项目的方法 使用从UCI机器学习仓库链接 获取的数据集开启一个机器学习项目 分类或回归模型的机器学习项目可以分成以
  • Linux Nginx配置静态html

    Linux Nginx配置静态html 第一次接触服务器时 对项目部署和域名部署感觉很新鲜 有意思 很神奇 开始学习Nginx配置静态的HTML 使用工具 MobaXterm CHS exe 第一步 将html的项目放入服务器 将自己做好的
  • 【华为OD机试真题 JAVA】信道分配

    JS版 华为OD机试真题 JS 信道分配 标题 信道分配 时间限制 1秒 内存限制 262144K 语言限制 不限 算法工程师小明面对着这样一个问题 需要将通信用的信道分配给尽量多的用户 信道的条件及分配规则如下 1 所有信道都有属性 阶
  • origin中把多个拟合曲线放在一张图

    双击其中一个 或者New一个graph 这里直接双击其中一个图 右键 找到layer contents 可以看到 一个scatter配一个polynomial fit line 把剩下的B C D对应的点和拟合曲线添加进去 注意 这里的pl
  • 01、Java并发 Java ExecutorService

    ExecutorService 是 Java java util concurrent 包的重要组成部分 是 Java JDK 提供的框架 用于简化异步模式下任务的执行 一般来说 ExecutorService 会自动提供一个线程池和相关
  • 程序员如何做副业?35岁前,千万别让死工资绊住你赚钱的步伐

    近年来互联网行情下降 好多人都在思考要不要搞个副业来抵御风险 这不又来事了 这两天又爆了互联网大裁员 继阿里 向社会输送人才 之后 京东又搞了个 毕业礼 整的小伙伴们人心惶惶 副业的关注度又一波升级 那今天我们就来聊聊 程序员做副业这件事
  • cef编译

    按照大神的一遍过 具体过程非常详细 链接https kefong blog csdn net article details 119908780 spm 1001 2101 3001 6650 2 utm medium distribute
  • 《C++ Primer(第5版)》学习笔记(第5章)

    第5章 语句 C 提供了条件执行语句 循环语句和用于中断当前控制流的跳转语句 本章将具体介绍这些语句 5 1 简单语句 空语句 最简单的语句是空语句 只有一个单独的分号 如在程序的某个地方语法上需要一条语句但是逻辑上不需要 此时应该使用空语