《C++ Primer》导学系列:第 5 章 - 语句

5.1 简单语句

5.1.1 基本概念

在C++中,简单语句是构成程序的基本单元。每个简单语句以分号(;)结束,可以是表达式、声明或空语句。

5.1.2 表达式语句

表达式语句是由表达式构成的语句,通常用于计算、赋值和函数调用。

示例代码
#include <iostream>

int main() {
    int a = 10;  // 赋值表达式语句
    a = a + 1;  // 计算并赋值
    std::cout << "a: " << a << std::endl;  // 函数调用语句

    return 0;
}

在这个示例中,每行代码都是一个表达式语句,执行赋值、计算和输出操作。

5.1.3 声明语句

声明语句用于声明变量、函数或类型,告诉编译器它们的存在和类型信息。

示例代码
#include <iostream>

int main() {
    int a = 10;  // 声明并初始化变量
    double b = 3.14;  // 声明并初始化变量
    std::cout << "a: " << a << ", b: " << b << std::endl;

    return 0;
}

在这个示例中,int adouble b是声明语句,它们声明并初始化了变量。

5.1.4 空语句

空语句仅由一个分号构成,不执行任何操作。通常用于需要语法上要求一个语句但实际不需要做任何事情的地方。

示例代码
#include <iostream>

int main() {
    int a = 0;
    while (a < 10) {
        ;  // 空语句,循环体不执行任何操作
        ++a;
    }
    std::cout << "a: " << a << std::endl;  // 输出 a 的值

    return 0;
}

在这个示例中,空语句用于while循环体,但没有实际操作。

5.1.5 复合语句(块)

复合语句由一对花括号{}包围的一系列语句组成,通常用于控制语句和函数体中。复合语句可以包含声明和其他语句,是形成控制结构的基础。

示例代码
#include <iostream>

int main() {
    int a = 0;
    {
        int b = 10;  // 复合语句中的声明
        a = a + b;  // 复合语句中的表达式
        std::cout << "Inside block: a: " << a << std::endl;
    }  // 复合语句的结束,b 的作用域结束

    std::cout << "Outside block: a: " << a << std::endl;

    return 0;
}

在这个示例中,复合语句(块)包含声明和表达式,块内的变量在块结束时作用域也结束。

重点与难点分析

重点

  1. 简单语句的种类和用法:理解表达式语句、声明语句和空语句的作用和用法。
  2. 复合语句的结构和作用:掌握复合语句的语法和应用场景,理解其在控制结构中的重要性。

难点

  1. 空语句的正确使用:初学者需要理解空语句的用途,避免在不适当的地方使用空语句。
  2. 复合语句中的作用域管理:掌握复合语句中变量的作用域,避免作用域混淆导致的错误。

练习题解析

  1. 练习5.1:编写一个包含多种简单语句的程序,输出结果。
  • 示例代码
#include <iostream>

int main() {
    int x = 5;  // 声明语句
    x = x + 2;  // 表达式语句
    ;  // 空语句
    std::cout << "x: " << x << std::endl;  // 函数调用语句

    return 0;
}

  1. 练习5.2:编写一个包含复合语句的程序,演示变量的作用域。
  • 示例代码
#include <iostream>

int main() {
    int a = 10;
    {
        int b = 20;
        a = a + b;
        std::cout << "Inside block: a: " << a << ", b: " << b << std::endl;
    }
    // b 的作用域结束,下面的代码会引发错误
    // std::cout << "Outside block: b: " << b << std::endl;  
    std::cout << "Outside block: a: " << a << std::endl;

    return 0;
}

总结与提高

本节总结

  1. 学习了简单语句的种类,包括表达式语句、声明语句和空语句,理解了它们在程序中的作用。
  2. 掌握了复合语句的结构和应用,理解了复合语句中变量的作用域。
  3. 理解了简单语句和复合语句的基本概念和用法,通过示例代码加深了对这些概念的理解。

提高建议

  1. 多练习简单语句的使用:通过编写各种包含不同简单语句的程序,熟悉它们的用法和作用。
  2. 深入理解复合语句中的作用域管理:通过实践掌握复合语句中变量作用域的管理,避免作用域混淆导致的错误。
  3. 优化代码结构:在编写代码时,合理使用复合语句组织代码,提高代码的可读性和维护性。

5.2 语句作用域

5.2.1 基本概念

在C++中,作用域(scope)定义了标识符(如变量、函数、类型等)在程序中可见和可访问的区域。理解作用域的概念有助于避免命名冲突和不必要的错误,提高代码的可读性和可维护性。

5.2.2 作用域类型

C++中主要有以下几种作用域:

  1. 全局作用域:在整个程序中都可见和可访问的标识符。
  2. 局部作用域:在函数或复合语句(块)内定义的标识符,仅在定义它们的块内可见。
  3. 类作用域:在类或结构体内定义的标识符,仅在该类或结构体的成员函数内可见。
  4. 命名空间作用域:在命名空间内定义的标识符,仅在该命名空间内可见。

5.2.3 全局作用域

全局作用域中的标识符在整个程序中都可见,通常在文件的最外层定义。

示例代码
#include <iostream>

int global_var = 100;  // 全局作用域变量

void func() {
    std::cout << "Global variable: " << global_var << std::endl;
}

int main() {
    std::cout << "Global variable in main: " << global_var << std::endl;
    func();
    return 0;
}

在这个示例中,global_var是一个全局作用域变量,在main函数和func函数中都可见和可访问。

5.2.4 局部作用域

局部作用域中的标识符在其定义的函数或块内可见,离开该块后不可见。

示例代码
#include <iostream>

void func() {
    int local_var = 10;  // 局部作用域变量
    std::cout << "Local variable in func: " << local_var << std::endl;
}

int main() {
    int local_var = 20;  // 局部作用域变量
    std::cout << "Local variable in main: " << local_var << std::endl;
    func();
    return 0;
}

在这个示例中,local_varmain函数和func函数中分别定义,并且只在各自的函数内可见。

5.2.5 类作用域

类作用域中的标识符在类或结构体的成员函数内可见。

示例代码
#include <iostream>

class MyClass {
public:
    MyClass(int val) : member_var(val) {}
    void display() {
        std::cout << "Member variable: " << member_var << std::endl;
    }
private:
    int member_var;  // 类作用域变量
};

int main() {
    MyClass obj(42);
    obj.display();
    return 0;
}

在这个示例中,member_var是类MyClass的成员变量,仅在类的成员函数display内可见。

5.2.6 命名空间作用域

命名空间作用域中的标识符在定义它们的命名空间内可见,可以避免全局命名冲突。

示例代码
#include <iostream>

namespace MyNamespace {
    int var = 50;  // 命名空间作用域变量
    void display() {
        std::cout << "Namespace variable: " << var << std::endl;
    }
}

int main() {
    MyNamespace::display();
    std::cout << "Namespace variable in main: " << MyNamespace::var << std::endl;
    return 0;
}

在这个示例中,vardisplay函数在命名空间MyNamespace内定义,只在该命名空间内可见。

重点与难点分析

重点:

  1. 作用域的基本概念:理解作用域的定义和作用,掌握不同类型的作用域及其应用场景。
  2. 局部和全局作用域:掌握局部和全局作用域的区别和使用方法,避免命名冲突和作用域混淆。
  3. 类作用域和命名空间作用域:理解类作用域和命名空间作用域的概念及其在实际编程中的应用。

难点

  1. 作用域管理:初学者需要通过实践理解作用域的管理,避免变量作用域混淆导致的错误。
  2. 命名空间的使用:掌握命名空间的定义和使用,特别是在大型项目中的应用,避免命名冲突。

练习题解析

  1. 练习5.3:编写一个包含全局变量和局部变量的程序,输出它们的值。
  • 示例代码
#include <iostream>

int global_var = 100;  // 全局变量

void func() {
    int local_var = 10;  // 局部变量
    std::cout << "Local variable in func: " << local_var << std::endl;
    std::cout << "Global variable in func: " << global_var << std::endl;
}

int main() {
    int local_var = 20;  // 局部变量
    std::cout << "Local variable in main: " << local_var << std::endl;
    std::cout << "Global variable in main: " << global_var << std::endl;
    func();
    return 0;
}

  1. 练习5.4:编写一个包含类作用域变量的程序,并在类的成员函数中输出其值。
  • 示例代码
#include <iostream>

class MyClass {
public:
    MyClass(int val) : member_var(val) {}
    void display() {
        std::cout << "Member variable: " << member_var << std::endl;
    }
private:
    int member_var;  // 类作用域变量
};

int main() {
    MyClass obj(42);
    obj.display();
    return 0;
}

  1. 练习5.5:编写一个使用命名空间的程序,定义命名空间变量并在命名空间内的函数中输出其值。
  • 示例代码
#include <iostream>

namespace MyNamespace {
    int var = 50;  // 命名空间变量
    void display() {
        std::cout << "Namespace variable: " << var << std::endl;
    }
}

int main() {
    MyNamespace::display();
    std::cout << "Namespace variable in main: " << MyNamespace::var << std::endl;
    return 0;
}

总结与提高

本节总结

  1. 学习了作用域的基本概念,理解了作用域在程序中的作用。
  2. 掌握了全局作用域、局部作用域、类作用域和命名空间作用域的定义和使用方法。
  3. 理解了不同作用域的应用场景,通过示例代码加深了对这些概念的理解。

提高建议

  1. 多练习不同作用域的使用:通过编写各种包含不同作用域的程序,熟悉它们的用法和作用。
  2. 深入理解作用域管理:通过实践掌握作用域的管理,避免变量作用域混淆导致的错误。
  3. 优化代码结构:在编写代码时,合理使用作用域管理变量和函数,提高代码的可读性和维护性,特别是在大型项目中使用命名空间避免命名冲突。

5.3 条件语句

5.3.1 基本概念

条件语句用于根据表达式的值来控制程序的执行流程。C++中的条件语句主要包括if语句和switch语句。

5.3.2 if语句

if语句根据一个条件表达式的布尔值决定是否执行一个代码块。if语句可以有一个可选的else分支和多个else if分支。

基本语法
if (condition) {
    // 当 condition 为 true 时执行的代码
} else if (another_condition) {
    // 当 another_condition 为 true 时执行的代码
} else {
    // 当所有条件都不满足时执行的代码
}

示例代码
#include <iostream>

int main() {
    int a = 10;

    if (a > 0) {
        std::cout << "a is positive" << std::endl;
    } else if (a == 0) {
        std::cout << "a is zero" << std::endl;
    } else {
        std::cout << "a is negative" << std::endl;
    }

    return 0;
}

在这个示例中,if语句检查a的值,并根据不同的条件执行不同的代码块。

5.3.3 switch语句

switch语句根据一个整数表达式的值选择要执行的代码块。每个代码块由一个或多个case标签标识,switch语句还可以包含一个可选的default标签。

基本语法
switch (expression) {
    case constant1:
        // 当 expression 等于 constant1 时执行的代码
        break;
    case constant2:
        // 当 expression 等于 constant2 时执行的代码
        break;
    default:
        // 当所有 case 都不匹配时执行的代码
}

示例代码
#include <iostream>

int main() {
    int a = 2;

    switch (a) {
        case 1:
            std::cout << "a is 1" << std::endl;
            break;
        case 2:
            std::cout << "a is 2" << std::endl;
            break;
        case 3:
            std::cout << "a is 3" << std::endl;
            break;
        default:
            std::cout << "a is not 1, 2, or 3" << std::endl;
    }

    return 0;
}

在这个示例中,switch语句检查a的值,并根据匹配的case标签执行相应的代码块。

5.3.4 嵌套条件语句

条件语句可以嵌套使用,即在一个条件语句的代码块中包含另一个条件语句。这种嵌套结构可以处理更复杂的条件判断。

示例代码
#include <iostream>

int main() {
    int a = 10;
    int b = 20;

    if (a > 0) {
        if (b > 0) {
            std::cout << "a and b are positive" << std::endl;
        } else {
            std::cout << "a is positive but b is not" << std::endl;
        }
    } else {
        std::cout << "a is not positive" << std::endl;
    }

    return 0;
}

在这个示例中,if语句嵌套在另一个if语句中,用于同时检查两个变量的值。

重点与难点分析

重点

  1. if语句的基本用法:掌握if语句的语法和用法,包括else ifelse分支的使用。
  2. switch语句的基本用法:理解switch语句的语法和用法,掌握case标签和default标签的使用。
  3. 嵌套条件语句:理解条件语句的嵌套用法,能够编写多层次的条件判断结构。

难点

  1. 条件语句的逻辑设计:初学者需要通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
  2. 避免代码重复和冗余:在使用条件语句时,应避免代码的重复和冗余,提高代码的可读性和维护性。

练习题解析

  1. 练习5.6:编写一个包含if-else语句的程序,根据用户输入的分数判断并输出相应的等级。
  • 示例代码
#include <iostream>

int main() {
    int score;
    std::cout << "Enter your score: ";
    std::cin >> score;

    if (score >= 90) {
        std::cout << "Grade: A" << std::endl;
    } else if (score >= 80) {
        std::cout << "Grade: B" << std::endl;
    } else if (score >= 70) {
        std::cout << "Grade: C" << std::endl;
    } else if (score >= 60) {
        std::cout << "Grade: D" << std::endl;
    } else {
        std::cout << "Grade: F" << std::endl;
    }

    return 0;
}

  1. 练习5.7:编写一个包含switch语句的程序,根据用户输入的月份输出相应的季节。
  • 示例代码
#include <iostream>

int main() {
    int month;
    std::cout << "Enter the month (1-12): ";
    std::cin >> month;

    switch (month) {
        case 12:
        case 1:
        case 2:
            std::cout << "Winter" << std::endl;
            break;
        case 3:
        case 4:
        case 5:
            std::cout << "Spring" << std::endl;
            break;
        case 6:
        case 7:
        case 8:
            std::cout << "Summer" << std::endl;
            break;
        case 9:
        case 10:
        case 11:
            std::cout << "Fall" << std::endl;
            break;
        default:
            std::cout << "Invalid month" << std::endl;
    }

    return 0;
}

  1. 练习5.8:编写一个嵌套if语句的程序,根据用户输入的年龄判断并输出相应的票价。
  • 示例代码
#include <iostream>

int main() {
    int age;
    std::cout << "Enter your age: ";
    std::cin >> age;

    if (age < 12) {
        std::cout << "Ticket price: $5" << std::endl;
    } else {
        if (age < 60) {
            std::cout << "Ticket price: $10" << std::endl;
        } else {
            std::cout << "Ticket price: $7" << std::endl;
        }
    }

    return 0;
}

总结与提高

本节总结

  1. 学习了条件语句的基本概念,掌握了if语句和switch语句的语法和用法。
  2. 理解了嵌套条件语句的结构和应用,能够编写多层次的条件判断结构。
  3. 通过示例代码和练习题,加深了对条件语句的理解和应用。

提高建议

  1. 多练习条件语句的使用:通过编写各种包含条件语句的程序,熟悉if语句和switch语句的用法。
  2. 深入理解条件语句的逻辑设计:通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
  3. 优化条件语句的结构:在编写条件语句时,避免代码的重复和冗余,提高代码的可读性和维护性。

5.4 迭代语句

5.4.1 基本概念

迭代语句,也称为循环语句,用于反复执行某段代码,直到满足特定条件为止。C++提供了三种主要的迭代语句:while循环、do while循环和for循环。

5.4.2 while循环

while循环在每次迭代之前测试条件表达式,如果条件为真,则执行循环体;如果条件为假,则退出循环。

基本语法
while (condition) {
    // 循环体
}

示例代码
#include <iostream>

int main() {
    int i = 0;

    while (i < 5) {
        std::cout << "i: " << i << std::endl;
        ++i;
    }

    return 0;
}

在这个示例中,while循环打印变量i的值,直到i不再小于5。

5.4.3 do while循环

do while循环与while循环类似,但不同的是,do while循环在每次迭代之后测试条件表达式。这意味着do while循环至少执行一次。

基本语法
do {
    // 循环体
} while (condition);

示例代码
#include <iostream>

int main() {
    int i = 0;

    do {
        std::cout << "i: " << i << std::endl;
        ++i;
    } while (i < 5);

    return 0;
}

在这个示例中,do while循环确保循环体至少执行一次,即使初始条件为假。

5.4.4 for循环

for循环通常用于需要明确控制循环变量的迭代次数的情况。for循环包含初始化语句、条件表达式和迭代语句。

基本语法
for (initialization; condition; iteration) {
    // 循环体
}

示例代码
#include <iostream>

int main() {
    for (int i = 0; i < 5; ++i) {
        std::cout << "i: " << i << std::endl;
    }

    return 0;
}

在这个示例中,for循环打印变量i的值,从0到4。

5.4.5 范围for语句

C++11引入了范围for语句(range-based for loop),用于遍历数组或其他容器。范围for语句使代码更加简洁和可读。

基本语法
for (declaration : expression) {
    // 循环体
}
  • declaration是用于引用容器元素的变量声明。
  • expression是一个可迭代的容器或范围。

示例代码
#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    for (int value : vec) {
        std::cout << "value: " << value << std::endl;
    }

    return 0;
}

在这个示例中,范围for循环遍历vec中的每个元素,并输出其值。

重点与难点分析

重点

  1. while循环和do while循环:掌握while循环和do while循环的基本语法和用法,理解它们的区别。
  2. for循环:理解for循环的基本语法,掌握初始化语句、条件表达式和迭代语句的作用。
  3. 范围for语句:掌握范围for语句的用法,理解其在遍历容器中的优势。

难点

  1. 循环控制:初学者需要通过实践掌握循环控制,包括循环的初始化、条件判断和迭代更新。
  2. 范围for语句的应用:熟悉范围for语句的语法和应用场景,特别是在处理标准库容器时的应用。

练习题解析

  1. 练习5.9:编写一个while循环,计算并输出1到10的和。
  • 示例代码
#include <iostream>

int main() {
    int sum = 0;
    int i = 1;

    while (i <= 10) {
        sum += i;
        ++i;
    }

    std::cout << "Sum: " << sum << std::endl;
    return 0;
}

  1. 练习5.10:编写一个do while循环,反复读取用户输入,直到输入0为止。
  • 示例代码
#include <iostream>

int main() {
    int number;

    do {
        std::cout << "Enter a number (0 to exit): ";
        std::cin >> number;
    } while (number != 0);

    std::cout << "Goodbye!" << std::endl;
    return 0;
}

  1. 练习5.11:编写一个for循环,输出1到10的平方。
  • 示例代码
#include <iostream>

int main() {
    for (int i = 1; i <= 10; ++i) {
        std::cout << "Square of " << i << " is " << i * i << std::endl;
    }

    return 0;
}

  1. 练习5.12:编写一个使用范围for语句的程序,输出数组中的每个元素。
  • 示例代码
#include <iostream>

int main() {
    int arr[] = {1, 2, 3, 4, 5};

    for (int value : arr) {
        std::cout << "value: " << value << std::endl;
    }

    return 0;
}

总结与提高

本节总结

  1. 学习了迭代语句的基本概念,掌握了while循环、do while循环和for循环的语法和用法。
  2. 理解了范围for语句的结构和应用,能够使用范围for语句遍历数组和标准库容器。
  3. 通过示例代码和练习题,加深了对迭代语句的理解和应用。

提高建议

  1. 多练习迭代语句的使用:通过编写各种包含迭代语句的程序,熟悉while循环、do while循环、for循环和范围for语句的用法。
  2. 深入理解循环控制:通过实践掌握循环的初始化、条件判断和迭代更新,确保循环的正确执行。
  3. 优化循环的效率:在编写循环时,注意循环的效率和性能,避免不必要的计算和重复操作,提高代码的执行效率。

5.5 跳转语句

5.5.1 基本概念

跳转语句用于在程序中改变控制流,直接跳转到程序的另一个部分。C++中的主要跳转语句包括breakcontinuegotoreturn和异常处理相关的throw

5.5.2 break语句

break语句用于立即终止所在的循环或switch语句,并跳转到紧接着循环或switch语句后的语句。

示例代码
#include <iostream>

int main() {
    for (int i = 0; i < 10; ++i) {
        if (i == 5) {
            break;  // 当 i 等于 5 时,跳出循环
        }
        std::cout << "i: " << i << std::endl;
    }

    std::cout << "Loop ended." << std::endl;
    return 0;
}

在这个示例中,当i等于5时,break语句终止for循环。

5.5.3 continue语句

continue语句用于跳过当前循环迭代的剩余部分,并继续执行下一次循环迭代。

示例代码
#include <iostream>

int main() {
    for (int i = 0; i < 10; ++i) {
        if (i % 2 == 0) {
            continue;  // 跳过偶数
        }
        std::cout << "i: " << i << std::endl;
    }

    return 0;
}

在这个示例中,continue语句跳过偶数的输出,只输出奇数。

5.5.4 goto语句

goto语句用于无条件跳转到程序中的指定标签。尽管goto语句很强大,但滥用会导致代码难以阅读和维护,因此通常应避免使用。

示例代码
#include <iostream>

int main() {
    int i = 0;

start:
    std::cout << "i: " << i << std::endl;
    ++i;
    if (i < 5) {
        goto start;  // 跳转到标签 start
    }

    return 0;
}

在这个示例中,goto语句跳转到标签start,实现了一个简单的循环。

5.5.5 return语句

return语句用于终止函数的执行,并将控制权返回给调用函数。return语句可以带有一个返回值,该值将作为函数调用的结果。

示例代码
#include <iostream>

int add(int a, int b) {
    return a + b;  // 返回两个整数的和
}

int main() {
    int result = add(5, 3);
    std::cout << "Result: " << result << std::endl;
    return 0;
}

在这个示例中,return语句将add函数的结果返回给调用者。

5.5.6 throw语句

throw语句用于抛出一个异常,使程序跳转到最近的异常处理器。异常处理在第18章详细讨论,这里只作简单介绍。

示例代码
#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("An error occurred");  // 抛出异常
    } catch (const std::runtime_error& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,throw语句抛出一个std::runtime_error异常,并在catch块中捕获和处理。

重点与难点分析

重点

  1. break和continue语句:掌握breakcontinue语句的基本用法,理解它们在循环中的作用。
  2. goto语句:了解goto语句的用法和潜在问题,避免滥用。
  3. return语句:理解return语句的基本用法,掌握其在函数中的作用。
  4. throw语句:初步了解throw语句的用法,理解其在异常处理中的作用。

难点

  1. 跳转控制:初学者需要通过实践掌握不同跳转语句的控制流,理解它们在程序中的具体应用场景。
  2. 异常处理:虽然throw语句在本章只是简单介绍,但理解其在异常处理中的作用是一个难点,需要在后续章节中深入学习。

练习题解析

  1. 练习5.13:编写一个程序,使用break语句终止循环。
  • 示例代码
#include <iostream>

int main() {
    for (int i = 0; i < 10; ++i) {
        if (i == 7) {
            break;  // 当 i 等于 7 时,跳出循环
        }
        std::cout << "i: " << i << std::endl;
    }

    std::cout << "Loop ended." << std::endl;
    return 0;
}

  1. 练习5.14:编写一个程序,使用continue语句跳过循环中的某些迭代。
  • 示例代码
#include <iostream>

int main() {
    for (int i = 0; i < 10; ++i) {
        if (i % 3 == 0) {
            continue;  // 跳过能被 3 整除的数字
        }
        std::cout << "i: " << i << std::endl;
    }

    return 0;
}

  1. 练习5.15:编写一个程序,使用goto语句实现循环,并注意避免滥用。
  • 示例代码
#include <iostream>

int main() {
    int i = 0;

start:
    std::cout << "i: " << i << std::endl;
    ++i;
    if (i < 5) {
        goto start;  // 跳转到标签 start
    }

    return 0;
}

  1. 练习5.16:编写一个包含return语句的函数,并调用该函数输出其返回值。
  • 示例代码
#include <iostream>

int multiply(int a, int b) {
    return a * b;  // 返回两个整数的乘积
}

int main() {
    int result = multiply(4, 5);
    std::cout << "Result: " << result << std::endl;
    return 0;
}

  1. 练习5.17:编写一个程序,使用throw语句抛出一个异常,并在catch块中处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("An error occurred");  // 抛出异常
    } catch (const std::runtime_error& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

总结与提高

本节总结

  1. 学习了跳转语句的基本概念,掌握了breakcontinuegotoreturnthrow语句的用法。
  2. 理解了跳转语句在控制程序流中的作用,并通过示例代码加深了对这些概念的理解。
  3. 初步了解了异常处理中的throw语句,理解其在异常处理中的作用。

提高建议

  1. 多练习跳转语句的使用:通过编写各种包含跳转语句的程序,熟悉breakcontinuegotoreturnthrow语句的用法。
  2. 深入理解跳转控制:通过实践掌握跳转语句的控制流,理解它们在程序中的具体应用场景。
  3. 避免滥用goto语句:在编写代码时,应尽量避免使用goto语句,以提高代码的可读性和维护性。
  4. 学习异常处理:后续章节中将深入学习异常处理,掌握throw语句及其相关的异常处理机制。

5.6 try语句块和异常处理

5.6.1 基本概念

异常处理是C++中用于应对程序运行过程中出现的错误情况的一种机制。通过异常处理,可以将错误与正常的代码逻辑分开,使程序更加健壮和易于维护。异常处理的核心机制包括try语句块、throw语句和catch语句。

5.6.2 try语句块

try语句块用于包围可能引发异常的代码。当try语句块中的代码抛出异常时,程序控制流将转移到相应的catch块中。

基本语法
try {
    // 可能引发异常的代码
} catch (exceptionType1 e1) {
    // 处理 exceptionType1 类型的异常
} catch (exceptionType2 e2) {
    // 处理 exceptionType2 类型的异常
}

5.6.3 throw语句

throw语句用于抛出一个异常,使程序跳转到最近的匹配catch块。throw语句可以抛出任意类型的对象,但通常抛出派生自std::exception的异常对象。

基本语法
throw exceptionObject;

示例代码
#include <iostream>
#include <stdexcept>

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero");  // 抛出异常
    }
    return a / b;
}

int main() {
    try {
        int result = divide(10, 0);
        std::cout << "Result: " << result << std::endl;
    } catch (const std::runtime_error& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,divide函数在除数为零时抛出std::runtime_error异常,并在main函数中捕获和处理该异常。

5.6.4 catch语句

catch语句用于捕获由try块抛出的异常,并执行处理代码。一个try块可以有多个catch块,每个catch块处理不同类型的异常。

基本语法
catch (exceptionType e) {
    // 处理异常的代码
}

示例代码
#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("An error occurred");
    } catch (const std::runtime_error& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Caught general exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,catch块捕获并处理std::runtime_error异常和其他std::exception类型的异常。

5.6.5 标准异常类

C++标准库提供了一些常用的异常类,这些类派生自std::exception。常见的标准异常类包括:

  • std::runtime_error
  • std::logic_error
  • std::out_of_range
  • std::invalid_argument
  • std::bad_alloc

示例代码
#include <iostream>
#include <stdexcept>

void checkIndex(int index, int size) {
    if (index < 0 || index >= size) {
        throw std::out_of_range("Index out of range");
    }
}

int main() {
    try {
        checkIndex(10, 5);
    } catch (const std::out_of_range& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,checkIndex函数在索引超出范围时抛出std::out_of_range异常,并在main函数中捕获和处理该异常。

重点与难点分析

重点

  1. 异常处理的基本概念:理解trythrowcatch语句的基本概念和用法。
  2. 标准异常类的使用:掌握常见的标准异常类及其应用场景。

难点

  1. 异常的传播和捕获:初学者需要通过实践理解异常的传播机制及如何正确捕获和处理异常。
  2. 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,需要掌握自定义异常类的方法。

练习题解析

  1. 练习5.18:编写一个函数,抛出一个标准异常,并在main函数中捕获并处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>

void func() {
    throw std::runtime_error("An error occurred in func");
}

int main() {
    try {
        func();
    } catch (const std::runtime_error& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

  1. 练习5.19:编写一个包含多个catch块的程序,捕获不同类型的异常。
  • 示例代码
#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::out_of_range("Out of range error");
    } catch (const std::out_of_range& e) {
        std::cout << "Caught out_of_range exception: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Caught general exception: " << e.what() << std::endl;
    }

    return 0;
}

  1. 练习5.20:编写一个函数,使用throw语句抛出一个自定义异常类,并在main函数中捕获并处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "My custom exception";
    }
};

void func() {
    throw MyException();
}

int main() {
    try {
        func();
    } catch (const MyException& e) {
        std::cout << "Caught MyException: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Caught general exception: " << e.what() << std::endl;
    }

    return 0;
}

总结与提高

本节总结

  1. 学习了异常处理的基本概念,掌握了trythrowcatch语句的用法。
  2. 理解了标准异常类的应用场景,并通过示例代码加深了对这些概念的理解。
  3. 掌握了异常的传播机制及其在程序中的具体应用。

提高建议

  1. 多练习异常处理的使用:通过编写各种包含异常处理的程序,熟悉trythrowcatch语句的用法。
  2. 深入理解异常的传播和捕获:通过实践掌握异常的传播机制及其在程序中的具体应用,确保异常能够被正确捕获和处理。
  3. 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,掌握自定义异常类的方法。

本主页会定期更新,为了能够及时获得更新,敬请关注我:点击左下角的关注。也可以关注公众号:请在微信上搜索公众号“iShare爱分享”并关注,或者扫描以下公众号二维码关注,以便在内容更新时直接向您推送。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是小语言模型?

介绍 近年来&#xff0c;人工智能领域取得了重大进展&#xff0c;尤其是在自然语言处理领域。GPT-3 和 PaLM 等大型语言模型因其出色的能力而备受关注&#xff0c;新一波小型语言模型正在兴起&#xff0c;它们在性能和效率之间提供了有希望的平衡。 什么是小语言模型&#xf…

Eigne库安装及使用教程

文章目录 1.Eigne库介绍2.Eigne库安装3.Eigne库使用4.some examples5.参考文献 1.Eigne库介绍 Eigen是可以用来进行线性代数、矩阵、向量操作等运算的C库&#xff0c;它里面包含了很多算法。它的License是MPL2。它支持多平台。 Eigen采用源码的方式提供给用户使用&#xff0c;在…

【日记】忽然想买根卷发棒了……(622 字)

正文 突然想买一根卷发棒了&#xff0c;虽然还没有多长&#xff0c;但刘海全搭在前面不太好看。忽然有些理解女孩子们的心情了。说起头发&#xff0c;晚上练头定下落接三角撑&#xff0c;终于找到了感觉。不过因为头要往前滑&#xff0c;刚开始在垫子上找感觉&#xff0c;那个垫…

《数字图像处理-OpenCV/Python》第16章:图像的特征描述

《数字图像处理-OpenCV/Python》第16章&#xff1a;图像的特征描述 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第16章&#xff1a;图像的特征描述 特征通常是针对图像中的目标或…

运营一个商城网站需要办理什么许可证?

搭建一个商城网站以下资质是必须要办理的&#xff1a;网站ICP备案以及增值电信业务经营许可证。 一、网站ICP备案 国家对提供互联网信息服务的ICP实行许可证制度。从而&#xff0c;ICP证成为网络经营的许可证&#xff0c;经营性网站必须办理ICP证&#xff0c;否则就属于非法经营…

Anvil Empires/铁砧帝国操作没反应、频繁掉线怎么办?

Anvil Empires是一款多人在线游戏&#xff0c;且规模非常大&#xff01;玩家需要在持续的在线世界中与成千上万的玩家一起发动战争。目前自定义服务器技术可以使多达 1000 名玩家能够在大规模的实时战斗&#xff0c;且战斗是由玩家在开放世界沙盒中有机地煽动的&#xff0c;所以…

windows 11 之 下载安装 curl

1. 背景 需要执行一个 curl 命令运行一个定时任务&#xff0c;之前博主用的mac&#xff0c;无需担心这个下载安装问题&#xff0c;现在转为 windows&#xff0c;需要下载安装crul命令。 2. 出现问题 3. 解决办法 3.1 下载最新的包 下载地址&#xff1a;https://curl.se/win…

【YOLOv8改进[注意力]】使用MLCA混合局部通道注意力改进c2f + 含全部代码和详细修改方式 + 手撕结构图

本文将进行在YOLOv8中使用MLCA混合局部通道注意力改进c2f 的实践,助力YOLOv8目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 MLCA 二 使用MLCA混合局部通道注意力改进c2f 1 整体修改

【大分享05】动态容差归档,打通不动产登记管理“最后一公里”

关注我们 - 数字罗塞塔计划 - 本篇是参加由电子文件管理推进联盟联合数字罗塞塔计划发起的“大分享”活动投稿文章&#xff0c;来自上海涵妍档案信息技术有限责任公司&#xff0c;作者&#xff1a;陈雪。 一、政策背景 在“互联网政务服务”的浪潮下&#xff0c;各级政府机构…

在整合spring boot+layui中解决Could not parse as expression: “的问题

首先查看报错信息&#xff0c;这里提示我们78行有问题 这里是[[]] 这个内联表达式出了问题&#xff0c;在当前所在的script标签中加入th:inlinenone&#xff0c;然后重启项目&#xff0c;成功解决&#xff01;

数理化解题研究杂志社数理化解题研究编辑部2024年第12期目录

教学设计与教学策略研究 聚焦数学思想 贯彻核心素养——以“函数的奇偶性”的教学设计为例 宋方宁;李硕; 2-4 高中数学课堂案例研究——探讨“教-学-评”一体化模式的应用 赖琰媛;曹小燕; 5-7 漫谈体验式教学在高中数学教学中的运用策略 林素珍; 15-17《数理化解题…

机器阅读理解技术在电网检修问答系统中的应用与创新

在当今快速发展的人工智能领域&#xff0c;机器阅读理解技术正逐渐成为提升行业工作效率的关键因素。本文将探讨思通数科大模型中的检修问答系统&#xff0c;这一系统通过先进的机器阅读理解技术&#xff0c;优化了电网维修工作的流程和效率。 一、机器阅读理解技术概述 机器…

掌握BigDecimal:Java中的精确数值比较技巧与实战解析

引言 在Java编程中&#xff0c;处理精确数值计算对于金融、科学和电子商务等领域来说至关重要。但由于浮点数在计算机内部表示的局限性&#xff0c;直接使用基本数据类型如float和double进行数值计算往往会引入舍入误差&#xff0c;造成精度降低。为了进行精确的数值计算&#…

代理配置SQUID

目录 SQUID代理服务器配置 监听浏览器访问记录 拒绝访问配置 SQUID代理服务器配置 实验系统 windows 10 xxxxx Roucky_linux9.4 192.168.226.22 监听浏览器访问记录 1. 安装squid yum install squid -y 2. 编辑squid配置文件 vim /etc/squid…

UDS诊断、ECU刷写、OTA升级、Tbox测试、CANoe实操

每天的直播时间&#xff1a; 周一至周五&#xff1a;20&#xff1a;00-23&#xff1a;00 周六与周日&#xff1a;9&#xff1a;00-12&#xff1a;00&#xff0c;14&#xff1a;00-17&#xff1a;00 TBOX 深圳 涉及过T-BOX测试吗Ota升级涉及的台架环境是什么样的&#xff1f;上…

CSS-0_1 CSS和层叠(样式优先级、内联样式、选择器 用户代理样式)

CSS 的本质就是声明规则 ——《深入解析CSS》 文章目录 CSS层叠和优先级用户代理样式请和用户代理样式和谐相处 选择器单选择器的优先级选择器组的优先级关于选择器的其他源码顺序尽可能的选择优先级低的选择器 内联样式内联样式和JavaScript !important多个 !important 碎碎念…

Git--Part4--多人协作

theme: nico 在之前的Git博客中&#xff0c;已经把Git本地相关的操作以及远程操作的介绍完了。如下&#xff1a; Git–Part1–基础操作 - 掘金 (juejin.cn)Git–Part2–分支管理 - 掘金 (juejin.cn)Git–Part3–远程操作 & 配置 & 标签管理 - 掘金 (juejin.cn) 这篇文…

计算机考研|双非计算机专业是考研还是就业?主要看这一点!

去看一看招聘就知道了&#xff0c;看看公司需要的开发或者计算机岗位要求的东西你在本科的时候有没有精通的 如果你发现&#xff1a;哎&#xff1f;看着招聘的要求好像本科多少都接触过&#xff0c;但现在已经忘得差不多了&#xff0c;或者是&#xff0c;哦&#xff0c;我知道…

2024/06/18--代码随想录算法7/17|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 力扣链接 动态规划5步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a; dp[i]: 下标i内&#xff08;包括i&#xff09;的房屋&#xff0c;最多可以偷到的金额为dp[i]确定递推公式 dp[i] max(dp[i-1], dp[i-2]nums[i]&#xff09;dp数…

LeetCode 2813.子序列最大优雅度

给你一个长度为 n 的二维整数数组 items 和一个整数 k 。 items[i] [profiti, categoryi]&#xff0c;其中 profiti 和 categoryi 分别表示第 i 个项目的利润和类别。 现定义 items 的 子序列 的 优雅度 可以用 total_profit distinct_categories^2 计算&#xff0c;其中 t…