1. 简单语句
1.1 表达式语句
描述:在 C++ 中,最常见的简单语句是表达式语句。它由一个表达式组成,并以分号结束。表达式语句可以包括函数调用、赋值操作、增减操作等。
示例代码:
1  | 
  | 
讲解:
int a = 5;初始化变量a,这是一个赋值表达式语句。a = a + 10;更新变量a的值。std::cout << a;调用了输出流对象的<<运算符函数。return 0;从main函数返回,结束程序。
1.2 声明语句
描述:声明语句用于声明变量、函数、类等标识符。
示例代码:
1  | 
  | 
讲解:
int add(int x, int y);是一个函数声明语句。int result = add(3, 4);在main中调用函数并声明变量。int add(int x, int y) { ... }是函数定义,提供了函数的实现。
2. 语句作用域
2.1 作用域的基本概念
描述:作用域定义了变量或其他标识符在程序中的可见范围。C++ 中主要有以下几种作用域:
- **局部作用域 (Local Scope)**:在函数或代码块内部定义的变量,仅在其所在的块内可见。
 - **全局作用域 (Global Scope)**:在所有函数外部定义的变量,在整个文件中可见。
 - **命名空间作用域 (Namespace Scope)**:在命名空间内部定义的标识符。
 
2.2 代码示例
1  | 
  | 
预期输出:
1  | In main() - globalVar: 10  | 
讲解:
globalVar在所有函数中都可见。mainVar仅在main函数内部可见。localVar仅在display函数内部可见。- 尝试在 
main中访问display函数的localVar将导致编译错误,因为它不在作用域内。 
2.3 代码块作用域
描述:通过使用花括号 {},可以创建新的代码块,从而定义局部作用域。
示例代码:
1  | 
  | 
预期输出:
1  | x before block: 10  | 
讲解:
- 在内部代码块中重新声明了变量 
x,该x只在代码块内有效,隐藏了外部的x。 - 离开代码块后,内部的 
x不再可见,外部的x依然有效。 
3. 条件语句
C++ 提供了多种条件语句,用于根据不同的条件执行不同的代码块。
3.1 if 语句
描述:if 语句用于在条件为真时执行特定的代码块。
语法:
1  | if (condition) {  | 
示例代码:
1  | 
  | 
讲解:
- 用户输入一个数字,如果 
number大于0,则输出 “The number is positive.”。 
3.2 if-else 语句
描述:if-else 语句在条件为假时执行另一个代码块。
语法:
1  | if (condition) {  | 
示例代码:
1  | 
  | 
讲解:
- 判断输入的数字是奇数还是偶数,并输出相应的结果。
 
3.3 else if 语句
描述:else if 允许在多重条件下执行不同的代码块。
语法:
1  | if (condition1) {  | 
示例代码:
1  | 
  | 
讲解:
- 根据分数范围判断并输出相应的等级。
 
3.4 switch 语句
描述:switch 语句根据变量的值选择执行的代码块,适用于离散的值。
语法:
1  | switch (expression) {  | 
示例代码:
1  | 
  | 
讲解:
- 根据输入的字母等级输出相应的评价。
 break语句防止代码“掉入”下一个case中。
4. 迭代语句
C++ 提供了多种循环结构,用于重复执行代码块。
4.1 for 循环
描述:for 循环用于已知循环次数的情况,结构紧凑。
语法:
1  | for (initialization; condition; increment) {  | 
示例代码:
1  | 
  | 
预期输出:
1  | Counting from 1 to 5:  | 
讲解:
- 初始化 
int i = 1。 - 条件 
i <= 5为真时执行循环体。 - 每次循环后执行 
++i,增加i的值。 - 最终输出 1 到 5。
 
4.2 while 循环
描述:while 循环在循环前判断条件,适合未知循环次数的情况。
语法:
1  | while (condition) {  | 
示例代码:
1  | 
  | 
预期输出:
1  | Counting from 1 to 5 using while loop:  | 
讲解:
- 初始化 
count = 1。 - 条件 
count <= 5为真时执行循环体。 - 每次循环后 
++count增加count的值。 
4.3 do-while 循环
描述:do-while 循环在循环后判断条件,保证至少执行一次循环体。
语法:
1  | do {  | 
示例代码:
1  | 
  | 
预期输出:
1  | Counting from 1 to 5 using do-while loop:  | 
讲解:
- 无论条件是否为真,
do块中的代码至少执行一次。 - 在本例中,
count从1开始,逐步增加到5。 
4.4 嵌套循环
描述:一个循环内部嵌套另一个循环,常用于多维数据结构的遍历。
示例代码:
1  | 
  | 
预期输出:
1  | Outer loop iteration 1:  | 
讲解:
- 外层 
for循环控制外层迭代次数。 - 内层 
for循环在每次外层循环中执行,控制内层迭代次数。 
5. 跳转语句
跳转语句用于改变程序的执行流。C++ 中主要有 break、continue、return 和 goto。
5.1 break 语句
描述:break 用于立即终止最近的循环或 switch 语句。
示例代码(在循环中使用 break):
1  | 
  | 
预期输出:
1  | 1 2 3 4  | 
讲解:
- 当 
i达到5时,break终止循环,停止进一步的迭代。 
5.2 continue 语句
描述:continue 用于跳过当前的循环迭代,继续下一次循环。
示例代码:
1  | 
  | 
预期输出:
1  | Even numbers between 1 and 10:  | 
讲解:
- 当 
i是奇数时,continue跳过本次循环,避免执行std::cout语句。 - 仅输出偶数。
 
5.3 return 语句
描述:return 用于从函数中返回一个值或结束函数执行。
示例代码:
1  | 
  | 
预期输出:
1  | The maximum of 10 and 20 is 20.  | 
讲解:
max函数根据条件返回较大的数,并退出函数执行。
5.4 goto 语句
描述:goto 允许无条件跳转到程序中指定的标签。虽然 goto 有时能简化代码,但不推荐频繁使用,因为它会使程序流程难以理解和维护。
示例代码:
1  | 
  | 
预期输出(输入为负数):
1  | Enter a positive number (negative to quit): -5  | 
讲解:
- 当输入负数时,
goto end;跳转到end标签,结束程序。 - 尽管可以使用 
goto,但建议使用更结构化的控制流,如循环和条件语句。 
6. 异常处理语句
异常处理用于应对程序运行过程中可能出现的错误情况,确保程序的健壮性和可靠性。
6.1 try, catch, 和 throw 语句
描述:
try块用于包含可能引发异常的代码。throw用于抛出异常。catch块用于捕获并处理异常。
基本语法:
1  | try {  | 
示例代码:
1  | 
  | 
预期输出:
1  | Enter numerator: 10  | 
讲解:
divide函数在分母为零时抛出std::invalid_argument异常。try块尝试执行divide函数。- 当异常发生时,执行对应的 
catch块,输出错误信息。 - 程序在异常处理后继续执行,而不会异常终止。
 
6.2 多重 catch 块
描述:可以为 try 块指定多个 catch 块,以处理不同类型的异常。
示例代码:
1  | 
  | 
预期输出(选择 1):
1  | Choose exception to throw (1: bad_alloc, 2: invalid_argument): 1  | 
讲解:
- 根据用户输入抛出不同类型的异常。
 - 对应的 
catch块分别处理不同的异常类型。 - 如果未匹配的异常被抛出且没有对应的 
catch块,将导致程序终止(未在此示例中展示)。 
6.3 throw 通常位置
描述:throw 语句可以在任何需要引发异常的位置使用,包括函数内部、嵌套调用中等。
示例代码:
1  | 
  | 
预期输出(输入为 3):
1  | Enter array index (0-4): 3  | 
预期输出(输入为 5):
1  | Enter array index (0-4): 5  | 
讲解:
getElement函数检查索引是否有效,如果无效则抛出std::out_of_range异常。main函数中的try块调用getElement,并在catch块中处理异常。
6.4 rethrow 异常
描述:可以在 catch 块中使用 throw 语句重新抛出捕获的异常,以便其他部分处理。
示例代码:
1  | 
  | 
预期输出:
1  | func2() caught an exception and is rethrowing it.  | 
讲解:
func1抛出异常。func2调用func1,捕获异常后重新抛出。main最终捕获并处理异常。
练习题
练习题 1:打印九九乘法表
题目描述
编写一个 C++ 程序,使用嵌套的 for 循环来打印标准的九九乘法表。输出的格式应整齐对齐,便于阅读。
要求
- 使用嵌套的 
for循环实现。 - 输出的乘法表应从 1×1 到 9×9。
 - 每行输出一个数字的乘法结果,例如第 3 行包含 
3×1=3到3×9=27。 - 确保输出格式整齐,便于阅读。
 
示例输出
1  | 1x1=1 1x2=2 1x3=3 1x4=4 1x5=5 1x6=6 1x7=7 1x8=8 1x9=9  | 
提示
- 使用两个嵌套的 
for循环:外层循环控制行数(1 到 9),内层循环控制列数(1 到 9)。 - 使用 
\t或者适当的空格来对齐输出结果。 - 可以使用 
std::cout进行输出。 
参考答案
1  | 
  | 
练习题 2:实现冒泡排序
题目描述
编写一个 C++ 程序,使用 冒泡排序算法 对用户输入的一组整数进行排序。冒泡排序是一种简单的排序算法,通过重复交换相邻的未按顺序排列的元素,将最大或最小的元素“冒泡”到序列的一端。
要求
- 输入:用户输入一组整数,首先输入整数的数量 
n,然后输入n个整数。 - 排序:使用冒泡排序算法对输入的整数进行升序排序。
 - 输出:显示排序前和排序后的整数序列。
 - 函数封装:将冒泡排序算法封装在一个独立的函数中,提高代码的模块化和可读性。
 
示例输入与输出
示例 1:
1  | 请输入整数的数量: 5  | 
示例 2:
1  | 请输入整数的数量: 8  | 
提示
- 冒泡排序的基本思想:通过多次遍历数组,每次比较相邻的元素并交换顺序错误的元素。每一轮遍历后,最大的元素会被移动到数组的末端。
 - 优化:如果在某一轮遍历中没有发生任何交换,说明数组已经有序,可以提前终止排序过程。
 - 函数设计:可以设计一个 
bubbleSort函数接收数组及其大小作为参数,并对数组进行排序。 
参考答案
1  | 
  | 
代码解释
**函数
bubbleSort**:参数:接收一个整数数组
arr和数组的大小n。逻辑
:
- 使用两层 
for循环实现冒泡排序。 - 外层循环控制需要进行的遍历次数,总共需要 
n-1轮。 - 内层循环进行相邻元素的比较和交换,每一轮内层循环会将当前未排序部分的最大元素移动到数组的末端。
 - 使用 
swapped标志位优化排序过程,如果一轮内层循环中没有发生任何交换,说明数组已经有序,提前终止排序。 
- 使用两层 
 交换操作:使用
std::swap函数交换两个元素的位置。
**函数
printArray**:- 功能:遍历数组并打印每个元素,便于观察排序前后的结果。
 
main函数:步骤
:
- 输入数组大小:提示用户输入要排序的整数数量 
n。 - 输入数组元素:动态分配一个大小为 
n的整数数组,并从用户处获取n个整数的输入。 - 打印排序前的数组:调用 
printArray函数显示原始数组。 - 执行冒泡排序:调用 
bubbleSort函数对数组进行排序。 - 打印排序后的数组:再次调用 
printArray函数显示排序后的数组。 - 内存管理:使用 
delete[]释放动态分配的内存,避免内存泄漏。 
- 输入数组大小:提示用户输入要排序的整数数量 
 
错误处理:
- 判断用户输入的数组大小 
n是否为正整数,否者输出错误信息并终止程序。 
- 判断用户输入的数组大小 
 
运行示例
1  | 请输入整数的数量: 5  | 
练习题 3:生成斐波那契数列
题目描述
编写一个 C++ 程序,生成并显示斐波那契数列。程序应允许用户指定生成数列的长度,并使用 循环结构 或 递归方法 来生成斐波那契数。
斐波那契数列是一个由 0 和 1 开始,后续的每个数都是前两个数之和的数列。例如:0, 1, 1, 2, 3, 5, 8, 13, …
要求
- 输入:用户输入要生成的斐波那契数的数量 
n。 - 生成:使用循环结构(如 
for或while循环)生成斐波那契数列。 - 输出:显示生成的斐波那契数列。
 - 函数封装:将生成斐波那契数列的逻辑封装在一个独立的函数中。
 
示例输入与输出
示例 1:
1  | 请输入要生成的斐波那契数的数量: 10  | 
示例 2:
1  | 请输入要生成的斐波那契数的数量: 5  | 
提示
斐波那契数列的定义
:
- 第 0 个斐波那契数是 0。
 - 第 1 个斐波那契数是 1。
 - 对于 
n >= 2,第n个斐波那契数是第n-1个数和第n-2个数的和。 
实现方法
:
- 迭代法:使用循环结构依次计算斐波那契数。
 - 递归法(高级):使用递归函数实现,但效率较低,通常不推荐用于较大的 
n。 
数据类型:根据
n的范围选择合适的数据类型,unsigned long long可以存储较大的斐波那契数。
参考答案(迭代法实现)
1  | 
  | 
代码解释
**函数
generateFibonacci**:参数:接收一个整数
n,表示要生成的斐波那契数的数量。返回值:返回一个
std::vector<unsigned long long>,包含生成的斐波那契数列。逻辑
:
- 如果 
n <= 0,返回一个空的向量。 - 初始化斐波那契数列的前两个数:0 和 1。
 - 使用一个 
for循环,从第三个数开始,依次计算当前数为前两个数之和,并将其添加到向量中。 
- 如果 
 
**函数
printFibonacci**:- 参数:接收一个 
const引用的斐波那契数列向量。 - 功能:遍历并打印斐波那契数列中的每个数,用空格分隔。
 
- 参数:接收一个 
 main函数:步骤
:
- 输入数量:提示用户输入要生成的斐波那契数的数量 
n。 - 输入验证:检查 
n是否为负数,若是则输出错误信息并终止程序。 - 生成数列:调用 
generateFibonacci函数生成斐波那契数列。 - 打印数列:调用 
printFibonacci函数显示生成的斐波那契数列。 
- 输入数量:提示用户输入要生成的斐波那契数的数量 
 
数据类型选择:
- 使用 
unsigned long long可以存储较大的斐波那契数,避免整数溢出。但需要注意,unsigned long long的范围有限,对于非常大的n,仍然会发生溢出。 
- 使用 
 
运行示例
1  | 请输入要生成的斐波那契数的数量: 10  | 
递归实现参考代码(可选)
1  | 
  | 
递归实现说明
优点
:
- 代码简洁,符合斐波那契数列的数学定义。
 
缺点
:
- 时间复杂度为指数级 
O(2^n),对于较大的n会非常低效。 - 递归深度过大可能导致栈溢出。
 
- 时间复杂度为指数级 
 使用场景:适合学习和理解递归概念,但在实际应用中需谨慎使用。
动态规划方法
动态规划通过存储已计算的值来避免重复计算,提高了效率。
1  | 
  |