用户工具

站点工具


cplus:第三章控制结构

第三章 控制结构

本章将详细介绍C++中的控制结构,包括条件语句、循环语句、跳转语句和switch语句,这些是控制程序流程的基本工具。

3.1 条件语句

3.1.1 if语句

if语句是C++中最基本的条件控制结构。

#include <iostream>
using namespace std;
 
int main() {
    int score = 85;
 
    // 简单if语句
    if (score >= 60) {
        cout << "Passed" << endl;
    }
 
    // if-else语句
    if (score >= 60) {
        cout << "Passed" << endl;
    } else {
        cout << "Failed" << endl;
    }
 
    // if-else if-else链
    if (score >= 90) {
        cout << "Grade: A" << endl;
    } else if (score >= 80) {
        cout << "Grade: B" << endl;
    } else if (score >= 70) {
        cout << "Grade: C" << endl;
    } else if (score >= 60) {
        cout << "Grade: D" << endl;
    } else {
        cout << "Grade: F" << endl;
    }
 
    return 0;
}

3.1.2 嵌套if语句

#include <iostream>
using namespace std;
 
int main() {
    int age = 25;
    bool hasLicense = true;
 
    // 嵌套if
    if (age >= 18) {
        if (hasLicense) {
            cout << "You can drive" << endl;
        } else {
            cout << "You need a license" << endl;
        }
    } else {
        cout << "You are too young to drive" << endl;
    }
 
    // 使用逻辑运算符简化
    if (age >= 18 && hasLicense) {
        cout << "You can drive" << endl;
    }
 
    // 悬空else问题
    int x = 5, y = 10;
    if (x > 0)
        if (y > 0)
            cout << "Both positive" << endl;
        else  // 这个else匹配内层的if
            cout << "y not positive" << endl;
 
    // 使用花括号避免歧义
    if (x > 0) {
        if (y > 0) {
            cout << "Both positive" << endl;
        }
    } else {
        cout << "x not positive" << endl;
    }
 
    return 0;
}

3.1.3 if语句的注意事项

#include <iostream>
using namespace std;
 
int main() {
    int* ptr = nullptr;
 
    // 常见错误:赋值而不是比较
    int x = 5;
    if (x = 10) {  // 警告:赋值操作,x变为10,条件为真
        cout << "This will always print" << endl;
    }
 
    // 安全做法:常量在前
    if (10 == x) {  // 如果写成 = 会编译错误
        cout << "x is 10" << endl;
    }
 
    // 检查空指针
    if (ptr) {  // 等价于 ptr != nullptr
        cout << "Pointer is valid" << endl;
    }
 
    // C++17 if with initializer
    if (int value = someFunction(); value > 0) {
        cout << "Positive: " << value << endl;
    }  // value在这里超出作用域
 
    return 0;
}

3.2 switch语句

3.2.1 基本语法

#include <iostream>
using namespace std;
 
int main() {
    int day = 3;
 
    switch (day) {
        case 1:
            cout << "Monday" << endl;
            break;
        case 2:
            cout << "Tuesday" << endl;
            break;
        case 3:
            cout << "Wednesday" << endl;
            break;
        case 4:
            cout << "Thursday" << endl;
            break;
        case 5:
            cout << "Friday" << endl;
            break;
        case 6:
        case 7:
            cout << "Weekend" << endl;
            break;
        default:
            cout << "Invalid day" << endl;
            break;
    }
 
    return 0;
}

3.2.2 switch的注意事项

#include <iostream>
using namespace std;
 
int main() {
    // switch表达式必须是整数类型
    // char、short、int、long、enum都可以
    char grade = 'B';
 
    switch (grade) {
        case 'A':
            cout << "Excellent" << endl;
            break;
        case 'B':
            cout << "Good" << endl;
            // 注意:这里没有break,会fall-through到case 'C'
        case 'C':
            cout << "Average" << endl;
            break;
        case 'D':
            cout << "Poor" << endl;
            break;
        case 'F':
            cout << "Fail" << endl;
            break;
        default:
            cout << "Invalid grade" << endl;
    }
 
    // C++17 [[fallthrough]] 属性
    int x = 1;
    switch (x) {
        case 1:
            cout << "One" << endl;
            [[fallthrough]];  // 明确表示故意fall-through
        case 2:
            cout << "Two" << endl;
            break;
    }
 
    // 不能使用字符串
    // string name = "hello";
    // switch (name) { }  // 错误!
 
    return 0;
}

3.2.3 枚举与switch

#include <iostream>
using namespace std;
 
enum class Color {
    Red,
    Green,
    Blue
};
 
enum Direction {
    North,
    South,
    East,
    West
};
 
int main() {
    Direction dir = East;
 
    switch (dir) {
        case North:
            cout << "Going North" << endl;
            break;
        case South:
            cout << "Going South" << endl;
            break;
        case East:
            cout << "Going East" << endl;
            break;
        case West:
            cout << "Going West" << endl;
            break;
    }
 
    // C++11强类型枚举
    Color c = Color::Red;
    switch (c) {
        case Color::Red:
            cout << "Red" << endl;
            break;
        case Color::Green:
            cout << "Green" << endl;
            break;
        case Color::Blue:
            cout << "Blue" << endl;
            break;
    }
 
    return 0;
}

3.3 循环语句

3.3.1 while循环

#include <iostream>
using namespace std;
 
int main() {
    // 基本while循环
    int count = 0;
    while (count < 5) {
        cout << "Count: " << count << endl;
        count++;
    }
 
    // 读取输入直到遇到特定值
    int number;
    cout << "Enter numbers (0 to stop): " << endl;
    while (cin >> number && number != 0) {
        cout << "You entered: " << number << endl;
    }
 
    // 无限循环(需要break)
    int sum = 0;
    int n;
    while (true) {
        cout << "Enter a number (-1 to stop): ";
        cin >> n;
        if (n == -1) break;
        sum += n;
    }
    cout << "Sum: " << sum << endl;
 
    // do-while循环(至少执行一次)
    int choice;
    do {
        cout << "\nMenu:" << endl;
        cout << "1. Option 1" << endl;
        cout << "2. Option 2" << endl;
        cout << "3. Exit" << endl;
        cout << "Enter choice: ";
        cin >> choice;
 
        switch (choice) {
            case 1: cout << "Option 1 selected" << endl; break;
            case 2: cout << "Option 2 selected" << endl; break;
            case 3: cout << "Goodbye" << endl; break;
            default: cout << "Invalid choice" << endl;
        }
    } while (choice != 3);
 
    return 0;
}

3.3.2 for循环

#include <iostream>
using namespace std;
 
int main() {
    // 基本for循环
    for (int i = 0; i < 5; i++) {
        cout << "i = " << i << endl;
    }
 
    // 多种变体
    // 1. 省略初始化
    int j = 0;
    for (; j < 5; j++) {
        cout << "j = " << j << endl;
    }
 
    // 2. 省略条件(无限循环)
    for (int k = 0; ; k++) {
        if (k >= 5) break;
        cout << "k = " << k << endl;
    }
 
    // 3. 省略更新
    for (int m = 0; m < 5; ) {
        cout << "m = " << m << endl;
        m++;
    }
 
    // 4. 多重初始化(C++允许)
    for (int a = 0, b = 10; a < b; a++, b--) {
        cout << "a = " << a << ", b = " << b << endl;
    }
 
    // 5. 范围for循环(C++11)
    int arr[] = {1, 2, 3, 4, 5};
    for (int x : arr) {
        cout << x << " ";
    }
    cout << endl;
 
    // 使用引用修改元素
    for (int& x : arr) {
        x *= 2;
    }
 
    // 使用auto(C++11)
    for (auto x : arr) {
        cout << x << " ";
    }
    cout << endl;
 
    return 0;
}

3.3.3 嵌套循环

#include <iostream>
#include <iomanip>
using namespace std;
 
int main() {
    // 打印乘法表
    cout << "Multiplication Table:" << endl;
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {
            cout << j << "x" << i << "=" << setw(2) << i * j << " ";
        }
        cout << endl;
    }
 
    // 打印金字塔
    int rows = 5;
    for (int i = 1; i <= rows; i++) {
        // 打印空格
        for (int j = 1; j <= rows - i; j++) {
            cout << " ";
        }
        // 打印星号
        for (int k = 1; k <= 2 * i - 1; k++) {
            cout << "*";
        }
        cout << endl;
    }
 
    // 使用break跳出内层循环
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (i * j > 20) {
                break;  // 只跳出内层循环
            }
            cout << i * j << " ";
        }
        cout << endl;
    }
 
    return 0;
}

3.4 跳转语句

3.4.1 break语句

#include <iostream>
using namespace std;
 
int main() {
    // 在switch中使用
    int choice = 2;
    switch (choice) {
        case 1:
            cout << "One" << endl;
            break;
        case 2:
            cout << "Two" << endl;
            break;  // 跳出switch
        case 3:
            cout << "Three" << endl;
            break;
    }
 
    // 在循环中使用
    for (int i = 0; i < 100; i++) {
        if (i == 10) {
            break;  // 跳出循环
        }
        cout << i << " ";
    }
    cout << endl;
 
    // 查找第一个能被7和13整除的数
    int num = 1;
    while (true) {
        if (num % 7 == 0 && num % 13 == 0) {
            cout << "Found: " << num << endl;  // 91
            break;
        }
        num++;
    }
 
    return 0;
}

3.4.2 continue语句

#include <iostream>
using namespace std;
 
int main() {
    // 跳过偶数
    for (int i = 0; i < 10; i++) {
        if (i % 2 == 0) {
            continue;  // 跳过本次循环剩余部分
        }
        cout << i << " ";  // 只打印奇数
    }
    cout << endl;
 
    // 只处理正数
    int numbers[] = {1, -2, 3, -4, 5, -6, 7};
    int sum = 0;
    for (int num : numbers) {
        if (num < 0) {
            continue;  // 跳过负数
        }
        sum += num;
    }
    cout << "Sum of positives: " << sum << endl;  // 16
 
    // 在while中使用continue要小心
    int x = 0;
    while (x < 10) {
        x++;  // 先递增!
        if (x % 3 == 0) {
            continue;
        }
        cout << x << " ";
    }
    cout << endl;
 
    return 0;
}

3.4.3 goto语句

#include <iostream>
using namespace std;
 
int main() {
    // goto语句(尽量避免使用)
    int i = 0;
 
loop_start:
    if (i >= 5) {
        goto loop_end;
    }
    cout << "i = " << i << endl;
    i++;
    goto loop_start;
 
loop_end:
    cout << "Loop finished" << endl;
 
    // goto的一个合理使用场景:跳出多层循环
    for (int a = 0; a < 10; a++) {
        for (int b = 0; b < 10; b++) {
            for (int c = 0; c < 10; c++) {
                if (a * b * c == 27) {
                    cout << "Found: a=" << a << ", b=" << b << ", c=" << c << endl;
                    goto found;  // 跳出所有循环
                }
            }
        }
    }
 
found:
    cout << "Search complete" << endl;
 
    // 更好的替代:使用函数和return
    // 或使用标志变量
    bool found2 = false;
    for (int a = 0; a < 10 && !found2; a++) {
        for (int b = 0; b < 10 && !found2; b++) {
            for (int c = 0; c < 10; c++) {
                if (a * b * c == 27) {
                    cout << "Found: " << a << ", " << b << ", " << c << endl;
                    found2 = true;
                    break;
                }
            }
        }
    }
 
    return 0;
}

3.4.4 return语句

#include <iostream>
using namespace std;
 
// 从函数返回值
int max(int a, int b) {
    if (a > b) {
        return a;  // 提前返回
    }
    return b;
}
 
// void函数中的return
void printPositive(int n) {
    if (n <= 0) {
        cout << "Not positive" << endl;
        return;  // 提前结束函数
    }
    cout << "Positive: " << n << endl;
}
 
// main函数中的return
int main() {
    cout << max(10, 20) << endl;
 
    printPositive(5);
    printPositive(-3);
 
    // return 0表示程序成功结束
    return 0;
    // 或者省略,C++会自动return 0
}

3.5 C++17新特性

3.5.1 if和switch的初始化语句

#include <iostream>
#include <map>
using namespace std;
 
int main() {
    map<string, int> scores;
    scores["Alice"] = 90;
    scores["Bob"] = 85;
 
    // C++17: if with initializer
    if (auto it = scores.find("Alice"); it != scores.end()) {
        cout << "Alice's score: " << it->second << endl;
    }
    // it在这里不可见,避免污染外部作用域
 
    // C++17: switch with initializer
    switch (int choice = 2; choice) {
        case 1: cout << "One" << endl; break;
        case 2: cout << "Two" << endl; break;
        default: cout << "Other" << endl;
    }
 
    // 实际应用:锁的自动管理
    // if (lock_guard<mutex> lock(mtx); shared_data.ready) {
    //     process(shared_data.value);
    // }
 
    return 0;
}

3.6 最佳实践

3.6.1 代码风格建议

#include <iostream>
using namespace std;
 
int main() {
    // 1. 总是使用花括号,即使只有一条语句
    if (true) {
        cout << "Good practice" << endl;
    }
 
    // 避免这样:
    // if (true)
    //     cout << "Risky" << endl;
    //     cout << "This always executes!" << endl;  // 不是if的一部分
 
    // 2. 避免深层嵌套,使用提前返回
    int value = 10;
 
    // 不好的写法
    if (value > 0) {
        if (value < 100) {
            if (value % 2 == 0) {
                cout << "Valid even number" << endl;
            }
        }
    }
 
    // 好的写法
    if (value <= 0) {
        cout << "Not positive" << endl;
    } else if (value >= 100) {
        cout << "Too large" << endl;
    } else if (value % 2 != 0) {
        cout << "Not even" << endl;
    } else {
        cout << "Valid even number" << endl;
    }
 
    // 或者使用guard clause
    if (value <= 0 || value >= 100) {
        cout << "Out of range" << endl;
    } else if (value % 2 != 0) {
        cout << "Not even" << endl;
    } else {
        cout << "Valid even number" << endl;
    }
 
    // 3. switch中使用枚举代替整数
    enum class Operation { Add, Subtract, Multiply, Divide };
    Operation op = Operation::Add;
 
    switch (op) {
        case Operation::Add:      /* ... */ break;
        case Operation::Subtract: /* ... */ break;
        case Operation::Multiply: /* ... */ break;
        case Operation::Divide:   /* ... */ break;
    }
 
    // 4. 范围for循环优先
    int arr[] = {1, 2, 3, 4, 5};
 
    // 推荐
    for (int x : arr) {
        cout << x << " ";
    }
 
    // 不推荐
    for (int i = 0; i < 5; i++) {
        cout << arr[i] << " ";
    }
 
    return 0;
}

3.7 本章小结

本章我们学习了:

  • if语句的各种形式:简单if、if-else、if-else if链
  • switch语句的用法和注意事项(break、fall-through)
  • 三种循环:while、do-while、for
  • 范围for循环(C++11)
  • 跳转语句:break、continue、goto、return
  • C++17的if/switch初始化语句
  • 控制结构的最佳实践

练习题

基础练习:

1. 编写程序判断一个年份是否是闰年。闰年条件:

  1. 能被4整除但不能被100整除,或
  2. 能被400整除

2. 使用switch语句实现简单计算器,支持+、-、*、/运算

3. 编写程序打印斐波那契数列的前n项(使用循环)

4. 编写程序判断一个数是否是质数

进阶练习:

5. 实现数字猜测游戏:

  1. 程序随机生成1-100的数字
  2. 用户猜测,程序提示“太大”或“太小”
  3. 记录猜测次数
  4. 允许用户选择是否继续游戏

6. 打印菱形图案,用户可以输入行数

7. 编写程序找出1-1000之间的所有完数(等于其因子之和的数)

思考题:

8. 分析以下代码的输出:

 <code cpp>
 int i = 0;
 while (i++ < 5) {
     cout << i << " ";
 }
 </code>

9. 比较for、while、do-while的适用场景,各举一例

10. 研究C++20的ranges库如何改变循环的写法

参考答案

练习1参考:

bool isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

练习4参考:

bool isPrime(int n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;
 
    for (int i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}

练习6参考:

#include <iostream>
using namespace std;
 
int main() {
    int n;
    cout << "Enter number of rows (odd): ";
    cin >> n;
 
    int half = n / 2;
 
    // 上半部分
    for (int i = 0; i <= half; i++) {
        for (int j = 0; j < half - i; j++) cout << " ";
        for (int j = 0; j < 2 * i + 1; j++) cout << "*";
        cout << endl;
    }
 
    // 下半部分
    for (int i = half - 1; i >= 0; i--) {
        for (int j = 0; j < half - i; j++) cout << " ";
        for (int j = 0; j < 2 * i + 1; j++) cout << "*";
        cout << endl;
    }
 
    return 0;
}

下一章

继续学习:第四章 函数

cplus/第三章控制结构.txt · 最后更改: 127.0.0.1