第3章:控制结构与函数

🎯 学习目标

本章将深入探讨C/C++中的控制结构和函数,这是构建复杂程序逻辑的基础。通过本章学习,你将能够:

  • 理解控制结构:掌握条件语句、循环语句和跳转语句的使用方法
  • 掌握函数编程:理解函数的定义、调用、参数传递和返回值机制
  • 运用逻辑思维:培养结构化编程思维,能够设计清晰的程序逻辑
  • 构建模块化程序:学会将复杂问题分解为函数模块,提高代码复用性

📚 知识结构

控制结构与函数
├── 控制结构
│   ├── 条件语句
│   │   ├── if-else语句
│   │   ├── 嵌套if语句
│   │   └── switch-case语句
│   ├── 循环语句
│   │   ├── for循环
│   │   ├── while循环
│   │   └── do-while循环
│   └── 跳转语句
│       ├── break语句
│       ├── continue语句
│       └── goto语句(不推荐)
├── 函数编程
│   ├── 函数基础
│   │   ├── 函数定义和声明
│   │   ├── 函数调用
│   │   └── 返回值
│   ├── 参数传递
│   │   ├── 值传递
│   │   ├── 引用传递
│   │   └── 指针传递
│   ├── 高级特性
│   │   ├── 函数重载
│   │   ├── 默认参数
│   │   └── 内联函数
│   └── 递归函数
└── 综合应用
    ├── 菜单驱动程序
    ├── 游戏开发
    └── 算法实现

🔍 核心概念详解

3.1 条件语句

条件语句允许程序根据不同的条件执行不同的代码块,是实现程序逻辑分支的基础。

3.1.1 if-else语句

if-else语句是最基本的条件语句,用于根据条件表达式的真假来决定程序的执行路径。

基本语法

if (condition) {
    // 条件为真时执行的语句
} else {
    // 条件为假时执行的语句
}

多分支if-else if结构

if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else if (score >= 70) {
    grade = 'C';
} else if (score >= 60) {
    grade = 'D';
} else {
    grade = 'F';
}

嵌套if语句

if (age >= 18) {
    if (hasLicense) {
        cout << "可以驾驶汽车" << endl;
    } else {
        cout << "需要考取驾照" << endl;
    }
} else {
    cout << "年龄未满18岁" << endl;
}
3.1.2 switch-case语句

switch-case语句用于多分支选择,当需要根据一个表达式的不同值执行不同操作时特别有用。

基本语法

switch (expression) {
    case value1:
        // 当expression等于value1时执行
        break;
    case value2:
        // 当expression等于value2时执行
        break;
    default:
        // 当expression不匹配任何case时执行
        break;
}

使用示例

switch (menuChoice) {
    case 1:
        showStudentInfo();
        break;
    case 2:
        addStudent();
        break;
    case 3:
        deleteStudent();
        break;
    case 4:
        cout << "退出系统" << endl;
        return 0;
    default:
        cout << "无效选择,请重新输入" << endl;
        break;
}

3.2 循环语句

循环语句允许程序重复执行某段代码,直到满足特定条件为止。

3.2.1 for循环

for循环适用于已知循环次数的情况,语法结构紧凑。

基本语法

for (initialization; condition; update) {
    // 循环体
}

使用示例

// 打印1到10的数字
for (int i = 1; i <= 10; i++) {
    cout << i << " ";
}

// 遍历数组
int numbers[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
    cout << numbers[i] << endl;
}
3.2.2 while循环

while循环适用于循环次数不确定,需要根据条件判断的情况。

基本语法

while (condition) {
    // 循环体
}

使用示例

int count = 0;
while (count < 5) {
    cout << "Count: " << count << endl;
    count++;
}
3.2.3 do-while循环

do-while循环至少执行一次,然后才检查条件。

基本语法

do {
    // 循环体
} while (condition);

使用示例

int choice;
do {
    cout << "请输入选择(1-5):";
    cin >> choice;
    processChoice(choice);
} while (choice != 5);  // 5表示退出

3.3 跳转语句

跳转语句用于改变程序的正常执行流程。

3.3.1 break语句

break语句用于立即退出循环或switch语句。

// 在循环中使用break
for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        break;  // 当i等于5时退出循环
    }
    cout << i << " ";
}
// 输出:1 2 3 4
3.3.2 continue语句

continue语句用于跳过当前循环的剩余语句,直接进入下一次循环。

// 跳过偶数,只打印奇数
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue;  // 跳过偶数
    }
    cout << i << " ";
}
// 输出:1 3 5 7 9

3.4 函数基础

函数是程序的基本模块,用于封装可重用的代码逻辑。

3.4.1 函数定义和声明

函数声明(原型):

return_type function_name(parameter_list);

函数定义(实现):

return_type function_name(parameter_list) {
    // 函数体
    return value;  // 如果返回类型不是void
}

示例

// 函数声明
int add(int a, int b);
double calculateArea(double radius);
void printMessage(string message);

// 函数定义
int add(int a, int b) {
    return a + b;
}

double calculateArea(double radius) {
    return 3.14159 * radius * radius;
}

void printMessage(string message) {
    cout << message << endl;
}
3.4.2 函数调用

函数调用是执行函数代码的过程。

int result = add(5, 3);                    // 调用add函数
double area = calculateArea(2.5);        // 调用calculateArea函数
printMessage("Hello, World!");         // 调用printMessage函数

3.5 参数传递机制

C++提供了多种参数传递方式,每种方式都有其特定的用途。

3.5.1 值传递

值传递是默认的参数传递方式,函数接收参数的副本。

void modifyValue(int x) {
    x = x + 10;  // 只修改副本,不影响原值
    cout << "函数内x = " << x << endl;
}

int main() {
    int num = 5;
    modifyValue(num);
    cout << "函数外num = " << num << endl;  // num仍然是5
    return 0;
}
3.5.2 引用传递

引用传递允许函数直接修改原变量的值。

void modifyValue(int& x) {  // 使用引用符号&
    x = x + 10;  // 直接修改原值
    cout << "函数内x = " << x << endl;
}

int main() {
    int num = 5;
    modifyValue(num);
    cout << "函数外num = " << num << endl;  // num现在是15
    return 0;
}
3.5.3 指针传递

指针传递通过地址来访问和修改变量。

void modifyValue(int* x) {  // 使用指针参数
    *x = *x + 10;  // 通过指针修改原值
    cout << "函数内*x = " << *x << endl;
}

int main() {
    int num = 5;
    modifyValue(&num);  // 传递地址
    cout << "函数外num = " << num << endl;  // num现在是15
    return 0;
}

3.6 函数高级特性

3.6.1 函数重载

函数重载允许定义多个同名函数,但参数列表必须不同。

// 重载函数示例
int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int add(int a, int b, int c) {
    return a + b + c;
}

// 使用重载函数
int main() {
    cout << add(5, 3) << endl;        // 调用第一个函数
    cout << add(5.5, 3.3) << endl;    // 调用第二个函数
    cout << add(1, 2, 3) << endl;   // 调用第三个函数
    return 0;
}
3.6.2 默认参数

默认参数允许在函数声明时为参数提供默认值。

// 带默认参数的函数
void printInfo(string name, int age = 18, string city = "北京") {
    cout << "姓名:" << name << ", 年龄:" << age << ", 城市:" << city << endl;
}

int main() {
    printInfo("张三");                    // 使用所有默认值
    printInfo("李四", 25);              // 指定年龄
    printInfo("王五", 30, "上海");    // 指定所有参数
    return 0;
}
3.6.3 内联函数

内联函数建议编译器将函数调用替换为函数体,适用于小而频繁调用的函数。

inline int max(int a, int b) {
    return (a > b) ? a : b;
}

inline double square(double x) {
    return x * x;
}

3.7 递归函数

递归函数是调用自身的函数,适用于解决可以分解为相似子问题的问题。

3.7.1 递归的基本要素
  1. 基本情况(Base Case):递归终止的条件
  2. 递归情况(Recursive Case):函数调用自身的情况
3.7.2 经典递归示例

阶乘计算

int factorial(int n) {
    if (n <= 1) {           // 基本情况
        return 1;
    } else {
        return n * factorial(n - 1);  // 递归情况
    }
}

斐波那契数列

int fibonacci(int n) {
    if (n <= 1) {           // 基本情况
        return n;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);  // 递归情况
    }
}

汉诺塔问题

void hanoi(int n, char source, char auxiliary, char target) {
    if (n == 1) {  // 基本情况
        cout << "移动盘子 1 从 " << source << " 到 " << target << endl;
    } else {
        // 递归情况
        hanoi(n - 1, source, target, auxiliary);     // 将n-1个盘子从源柱移到辅助柱
        cout << "移动盘子 " << n << " 从 " << source << " 到 " << target << endl;
        hanoi(n - 1, auxiliary, source, target);     // 将n-1个盘子从辅助柱移到目标柱
    }
}

💻 实践项目:智能游戏中心

项目概述

我们将创建一个综合性的游戏中心,集成多个经典游戏和实用工具,全面展示控制结构和函数的应用。

功能特性

  1. 主菜单系统:使用switch-case实现游戏选择
  2. 猜数字游戏:使用循环和条件语句
  3. 21点游戏:综合运用各种控制结构
  4. 计算器:函数封装和重载
  5. 成绩管理:文件操作和数据处理
  6. 系统设置:参数配置和状态管理

完整代码实现

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <random>
#include <ctime>
#include <iomanip>

using namespace std;

// 全局常量
const int MAX_GUESSES = 10;
const int BLACKJACK_LIMIT = 21;
const int DEALER_HIT_THRESHOLD = 17;
const string SETTINGS_FILE = "game_settings.txt";
const string SCORES_FILE = "game_scores.txt";

// 游戏设置结构体
struct GameSettings {
    int maxGuesses;
    int blackjackLimit;
    int dealerThreshold;
    bool soundEnabled;
    bool saveScores;
};

// 游戏成绩结构体
struct GameScore {
    string gameName;
    string playerName;
    int score;
    string date;
    string difficulty;
};

// 全局变量
GameSettings settings;
vector<GameScore> gameScores;

// 函数声明
void initializeGame();
void showMainMenu();
void playNumberGuessingGame();
void playBlackjackGame();
void showCalculator();
void manageScores();
void configureSettings();
void loadSettings();
void saveSettings();
void loadScores();
void saveScores();
void displayScores();

// 工具函数
int getRandomNumber(int min, int max);
bool askYesNoQuestion(const string& question);
void clearScreen();
void pauseScreen();
string getCurrentDate();

// 数学函数重载
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);

// 递归函数
int factorial(int n);
int fibonacci(int n);
int gcd(int a, int b);
int power(int base, int exponent);

// 主函数
int main() {
    initializeGame();
    
    int choice;
    bool running = true;
    
    while (running) {
        showMainMenu();
        cout << "请输入您的选择(1-6):";
        cin >> choice;
        
        switch (choice) {
            case 1:
                playNumberGuessingGame();
                break;
            case 2:
                playBlackjackGame();
                break;
            case 3:
                showCalculator();
                break;
            case 4:
                manageScores();
                break;
            case 5:
                configureSettings();
                break;
            case 6:
                cout << "感谢使用游戏中心,再见!" << endl;
                running = false;
                break;
            default:
                cout << "无效选择,请重新输入!" << endl;
                pauseScreen();
                break;
        }
    }
    
    saveSettings();
    saveScores();
    return 0;
}

// 初始化游戏
void initializeGame() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=          智能游戏中心               =" << endl;
    cout << "=        Smart Game Center            =" << endl;
    cout << "========================================" << endl;
    cout << endl;
    
    // 设置随机数种子
    srand(static_cast<unsigned int>(time(nullptr)));
    
    // 加载设置和成绩
    loadSettings();
    loadScores();
    
    cout << "游戏初始化完成!" << endl;
    pauseScreen();
}

// 显示主菜单
void showMainMenu() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=          智能游戏中心               =" << endl;
    cout << "========================================" << endl;
    cout << "1. 猜数字游戏" << endl;
    cout << "2. 21点游戏" << endl;
    cout << "3. 多功能计算器" << endl;
    cout << "4. 成绩管理" << endl;
    cout << "5. 系统设置" << endl;
    cout << "6. 退出游戏" << endl;
    cout << "========================================" << endl;
}

// 猜数字游戏
void playNumberGuessingGame() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=            猜数字游戏                =" << endl;
    cout << "========================================" << endl;
    
    string playerName;
    cout << "请输入您的名字:";
    cin >> playerName;
    
    int min, max;
    cout << "请输入数字范围(最小值 最大值):";
    cin >> min >> max;
    
    if (min >= max) {
        cout << "范围设置错误,使用默认值1-100" << endl;
        min = 1;
        max = 100;
    }
    
    int targetNumber = getRandomNumber(min, max);
    int guess;
    int attempts = 0;
    int maxAttempts = settings.maxGuesses;
    
    cout << "我已经想好了一个" << min << "到" << max << "之间的数字。" << endl;
    cout << "您有" << maxAttempts << "次机会来猜这个数字。" << endl;
    
    bool guessed = false;
    while (attempts < maxAttempts && !guessed) {
        cout << "第" << (attempts + 1) << "次猜测:";
        cin >> guess;
        
        if (cin.fail()) {
            cin.clear();
            cin.ignore(10000, '\n');
            cout << "请输入有效的数字!" << endl;
            continue;
        }
        
        attempts++;
        
        if (guess < targetNumber) {
            cout << "太小了!" << endl;
        } else if (guess > targetNumber) {
            cout << "太大了!" << endl;
        } else {
            guessed = true;
            cout << "恭喜您!猜对了!" << endl;
            cout << "您用了" << attempts << "次就猜中了。" << endl;
        }
        
        if (!guessed && attempts < maxAttempts) {
            cout << "还有" << (maxAttempts - attempts) << "次机会。" << endl;
        }
    }
    
    if (!guessed) {
        cout << "很遗憾,您没有猜中。正确答案是:" << targetNumber << endl;
    }
    
    // 保存成绩
    if (settings.saveScores && guessed) {
        GameScore score;
        score.gameName = "猜数字";
        score.playerName = playerName;
        score.score = max(100 - (attempts - 1) * 10, 10);  // 基础分100,每次猜测扣10分,最低10分
        score.date = getCurrentDate();
        score.difficulty = (max - min <= 50) ? "简单" : (max - min <= 200) ? "中等" : "困难";
        gameScores.push_back(score);
        cout << "成绩已保存!" << endl;
    }
    
    pauseScreen();
}

// 21点游戏
void playBlackjackGame() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=            21点游戏                =" << endl;
    cout << "========================================" << endl;
    
    string playerName;
    cout << "请输入您的名字:";
    cin >> playerName;
    
    bool playing = true;
    int playerMoney = 1000;
    
    while (playing && playerMoney > 0) {
        cout << "\n您当前有" << playerMoney << "元。" << endl;
        
        int bet;
        cout << "请输入赌注(1-" << playerMoney << "):";
        cin >> bet;
        
        if (bet <= 0 || bet > playerMoney) {
            cout << "赌注无效!" << endl;
            continue;
        }
        
        // 发牌
        int playerCard1 = getRandomNumber(1, 11);
        int playerCard2 = getRandomNumber(1, 11);
        int playerTotal = playerCard1 + playerCard2;
        
        int dealerCard1 = getRandomNumber(1, 11);
        int dealerCard2 = getRandomNumber(1, 11);
        int dealerTotal = dealerCard1 + dealerCard2;
        
        cout << "\n您的牌:" << playerCard1 << " 和 " << playerCard2 << " = " << playerTotal << endl;
        cout << "庄家的明牌:" << dealerCard1 << endl;
        
        // 玩家回合
        bool playerBusted = false;
        while (playerTotal < settings.blackjackLimit && !playerBusted) {
            cout << "是否继续要牌?(y/n):";
            char choice;
            cin >> choice;
            
            if (choice == 'y' || choice == 'Y') {
                int newCard = getRandomNumber(1, 11);
                playerTotal += newCard;
                cout << "您抽到:" << newCard << ",现在总共:" << playerTotal << endl;
                
                if (playerTotal > settings.blackjackLimit) {
                    playerBusted = true;
                    cout << "您爆牌了!" << endl;
                }
            } else {
                break;
            }
        }
        
        // 庄家回合
        if (!playerBusted) {
            cout << "\n庄家的暗牌是:" << dealerCard2 << " = " << dealerTotal << endl;
            
            while (dealerTotal < settings.dealerThreshold) {
                int newCard = getRandomNumber(1, 11);
                dealerTotal += newCard;
                cout << "庄家抽到:" << newCard << ",现在总共:" << dealerTotal << endl;
            }
        }
        
        // 判断胜负
        if (playerBusted) {
            cout << "您输了!" << endl;
            playerMoney -= bet;
        } else if (dealerTotal > settings.blackjackLimit) {
            cout << "庄家爆牌,您赢了!" << endl;
            playerMoney += bet;
        } else if (playerTotal > dealerTotal) {
            cout << "您赢了!" << endl;
            playerMoney += bet;
        } else if (playerTotal < dealerTotal) {
            cout << "您输了!" << endl;
            playerMoney -= bet;
        } else {
            cout << "平局!" << endl;
        }
        
        if (playerMoney > 0) {
            cout << "\n是否继续游戏?(y/n):";
            char continueGame;
            cin >> continueGame;
            playing = (continueGame == 'y' || continueGame == 'Y');
        }
    }
    
    cout << "\n游戏结束!" << endl;
    if (playerMoney <= 0) {
        cout << "您输光了所有的钱!" << endl;
    } else {
        cout << "您最终有" << playerMoney << "元。" << endl;
    }
    
    // 保存成绩
    if (settings.saveScores) {
        GameScore score;
        score.gameName = "21点";
        score.playerName = playerName;
        score.score = max(playerMoney / 10, 0);  // 分数为金钱的十分之一
        score.date = getCurrentDate();
        score.difficulty = "标准";
        gameScores.push_back(score);
        cout << "成绩已保存!" << endl;
    }
    
    pauseScreen();
}

// 多功能计算器
void showCalculator() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=            多功能计算器              =" << endl;
    cout << "========================================" << endl;
    
    int choice;
    bool running = true;
    
    while (running) {
        cout << "\n计算功能:" << endl;
        cout << "1. 基础运算" << endl;
        cout << "2. 科学计算" << endl;
        cout << "3. 数学函数" << endl;
        cout << "4. 递归计算" << endl;
        cout << "5. 返回主菜单" << endl;
        cout << "请选择功能(1-5):";
        cin >> choice;
        
        switch (choice) {
            case 1: {
                double a, b;
                char op;
                cout << "请输入表达式(如:3.5 + 2.1):";
                cin >> a >> op >> b;
                
                double result;
                switch (op) {
                    case '+':
                        result = add(a, b);
                        break;
                    case '-':
                        result = subtract(a, b);
                        break;
                    case '*':
                        result = multiply(a, b);
                        break;
                    case '/':
                        if (b != 0) {
                            result = divide(a, b);
                        } else {
                            cout << "错误:除数不能为0!" << endl;
                            continue;
                        }
                        break;
                    default:
                        cout << "无效的操作符!" << endl;
                        continue;
                }
                cout << "结果:" << a << " " << op << " " << b << " = " << result << endl;
                break;
            }
            case 2: {
                cout << "科学计算功能:" << endl;
                cout << "1. 阶乘" << endl;
                cout << "2. 斐波那契数列" << endl;
                cout << "3. 最大公约数" << endl;
                cout << "4. 幂运算" << endl;
                cout << "请选择(1-4):";
                int sciChoice;
                cin >> sciChoice;
                
                int n;
                switch (sciChoice) {
                    case 1: {
                        cout << "请输入非负整数:";
                        cin >> n;
                        if (n < 0) {
                            cout << "输入必须为非负整数!" << endl;
                        } else {
                            cout << n << "! = " << factorial(n) << endl;
                        }
                        break;
                    }
                    case 2: {
                        cout << "请输入项数:";
                        cin >> n;
                        if (n < 0) {
                            cout << "项数必须为非负整数!" << endl;
                        } else {
                            cout << "斐波那契数列前" << n << "项:";
                            for (int i = 0; i < n; i++) {
                                cout << fibonacci(i) << " ";
                            }
                            cout << endl;
                        }
                        break;
                    }
                    case 3: {
                        int a, b;
                        cout << "请输入两个正整数:";
                        cin >> a >> b;
                        if (a <= 0 || b <= 0) {
                            cout << "输入必须为正整数!" << endl;
                        } else {
                            cout << "GCD(" << a << ", " << b << ") = " << gcd(a, b) << endl;
                        }
                        break;
                    }
                    case 4: {
                        int base, exp;
                        cout << "请输入底数和指数:";
                        cin >> base >> exp;
                        if (exp < 0) {
                            cout << "指数必须为非负整数!" << endl;
                        } else {
                            cout << base << "^" << exp << " = " << power(base, exp) << endl;
                        }
                        break;
                    }
                    default:
                        cout << "无效选择!" << endl;
                        break;
                }
                break;
            }
            case 3: {
                cout << "数学函数功能开发中..." << endl;
                break;
            }
            case 4: {
                cout << "递归计算功能开发中..." << endl;
                break;
            }
            case 5:
                running = false;
                cout << "返回主菜单..." << endl;
                break;
            default:
                cout << "无效选择!" << endl;
                break;
        }
    }
}

// 成绩管理
void manageScores() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=            成绩管理                  =" << endl;
    cout << "========================================" << endl;
    
    displayScores();
    pauseScreen();
}

// 系统设置
void configureSettings() {
    clearScreen();
    cout << "========================================" << endl;
    cout << "=            系统设置                  =" << endl;
    cout << "========================================" << endl;
    
    cout << "当前设置:" << endl;
    cout << "1. 猜游戏最大尝试次数:" << settings.maxGuesses << endl;
    cout << "2. 21点上限:" << settings.blackjackLimit << endl;
    cout << "3. 庄家补牌阈值:" << settings.dealerThreshold << endl;
    cout << "4. 音效:" << (settings.soundEnabled ? "开启" : "关闭") << endl;
    cout << "5. 保存成绩:" << (settings.saveScores ? "开启" : "关闭") << endl;
    
    cout << "\n要修改设置吗?(y/n):";
    char choice;
    cin >> choice;
    
    if (choice == 'y' || choice == 'Y') {
        cout << "输入新的猜游戏最大尝试次数:";
        cin >> settings.maxGuesses;
        cout << "输入新的21点上限:";
        cin >> settings.blackjackLimit;
        cout << "输入新的庄家补牌阈值:";
        cin >> settings.dealerThreshold;
        settings.soundEnabled = askYesNoQuestion("是否开启音效?");
        settings.saveScores = askYesNoQuestion("是否保存成绩?");
        
        cout << "设置已更新!" << endl;
        saveSettings();
    }
    
    pauseScreen();
}

// 工具函数实现
int getRandomNumber(int min, int max) {
    static random_device rd;
    static mt19937 gen(rd());
    uniform_int_distribution<> dis(min, max);
    return dis(gen);
}

bool askYesNoQuestion(const string& question) {
    cout << question << " (y/n):";
    char choice;
    cin >> choice;
    return (choice == 'y' || choice == 'Y');
}

void clearScreen() {
    system("clear");  // Linux/Mac
    // system("cls");  // Windows
}

void pauseScreen() {
    cout << "\n按回车键继续...";
    cin.ignore();
    cin.get();
}

string getCurrentDate() {
    time_t now = time(nullptr);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d", localtime(&now));
    return string(buffer);
}

// 数学函数重载实现
double add(double a, double b) { return a + b; }
double subtract(double a, double b) { return a - b; }
double multiply(double a, double b) { return a * b; }
double divide(double a, double b) { return a / b; }
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }

// 递归函数实现
int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

int fibonacci(int n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int power(int base, int exponent) {
    if (exponent == 0) return 1;
    if (exponent == 1) return base;
    if (exponent % 2 == 0) {
        int half = power(base, exponent / 2);
        return half * half;
    } else {
        return base * power(base, exponent - 1);
    }
}

// 设置管理函数
void loadSettings() {
    ifstream file(SETTINGS_FILE);
    if (file.is_open()) {
        file >> settings.maxGuesses;
        file >> settings.blackjackLimit;
        file >> settings.dealerThreshold;
        file >> settings.soundEnabled;
        file >> settings.saveScores;
        file.close();
    } else {
        // 默认设置
        settings.maxGuesses = MAX_GUESSES;
        settings.blackjackLimit = BLACKJACK_LIMIT;
        settings.dealerThreshold = DEALER_HIT_THRESHOLD;
        settings.soundEnabled = true;
        settings.saveScores = true;
    }
}

void saveSettings() {
    ofstream file(SETTINGS_FILE);
    if (file.is_open()) {
        file << settings.maxGuesses << endl;
        file << settings.blackjackLimit << endl;
        file << settings.dealerThreshold << endl;
        file << settings.soundEnabled << endl;
        file << settings.saveScores << endl;
        file.close();
    }
}

// 成绩管理函数
void loadScores() {
    ifstream file(SCORES_FILE);
    if (file.is_open()) {
        GameScore score;
        while (file >> score.gameName >> score.playerName >> score.score >> score.date >> score.difficulty) {
            gameScores.push_back(score);
        }
        file.close();
    }
}

void saveScores() {
    ofstream file(SCORES_FILE);
    if (file.is_open()) {
        for (const auto& score : gameScores) {
            file << score.gameName << " " << score.playerName << " " 
                 << score.score << " " << score.date << " " << score.difficulty << endl;
        }
        file.close();
    }
}

void displayScores() {
    if (gameScores.empty()) {
        cout << "暂无成绩记录。" << endl;
        return;
    }
    
    cout << "\n游戏成绩记录:" << endl;
    cout << setw(15) << "游戏名称" 
         << setw(15) << "玩家姓名" 
         << setw(10) << "分数" 
         << setw(15) << "日期" 
         << setw(10) << "难度" << endl;
    cout << string(65, '-') << endl;
    
    for (const auto& score : gameScores) {
        cout << setw(15) << score.gameName 
             << setw(15) << score.playerName 
             << setw(10) << score.score 
             << setw(15) << score.date 
             << setw(10) << score.difficulty << endl;
    }
}

🎯 最佳实践

1. 控制结构使用原则

条件语句最佳实践

  • 使用清晰的条件表达式,避免复杂的嵌套
  • 优先使用switch-case处理多分支选择
  • 保持条件判断的逻辑简单明了
// 好的做法:清晰的条件判断
if (age >= 18 && hasLicense) {
    allowDriving();
} else if (age >= 16) {
    allowLearning();
} else {
    denyDriving();
}

// 避免:复杂的嵌套条件
if (age >= 18) {
    if (hasLicense) {
        if (!hasViolations) {
            allowDriving();
        } else {
            reviewCase();
        }
    } else {
        requireLicense();
    }
} else {
    denyDriving();
}

循环结构最佳实践

  • 选择合适的循环类型(for、while、do-while)
  • 确保循环有明确的退出条件
  • 避免无限循环
// 好的做法:明确的循环条件
for (int i = 0; i < arraySize; i++) {
    processElement(array[i]);
}

// 避免:可能导致无限循环
int i = 0;
while (i < arraySize) {
    processElement(array[i]);
    // 忘记递增i,可能导致无限循环
}

2. 函数设计原则

单一职责原则:每个函数应该只负责一个明确的任务

// 好的做法:函数职责单一
double calculateArea(double radius) {
    return PI * radius * radius;
}

void displayResult(double area) {
    cout << "圆的面积是:" << area << endl;
}

// 避免:函数承担过多职责
double calculateAndDisplay(double radius) {
    double area = PI * radius * radius;
    cout << "圆的面积是:" << area << endl;
    return area;
}

函数命名规范

  • 使用动词或动词短语描述函数的功能
  • 保持命名的一致性和描述性
  • 避免过于简单或过于复杂的命名
// 好的命名
double calculateAverage(const vector<int>& numbers);
bool isValidEmail(const string& email);
void sortArray(int arr[], int size);

// 需要改进的命名
double calc(const vector<int>& numbers);  // 太简单
bool check(const string& email);            // 不够具体
void process(int arr[], int size);          // 太笼统

3. 参数传递选择

值传递:适用于基本数据类型和小对象

int add(int a, int b);  // 基本类型,使用值传递

引用传递:适用于需要修改原值或大型对象

void updateStudentInfo(Student& student);  // 需要修改原值
void processLargeData(const vector<int>& data);  // 大型对象,使用const引用避免复制

指针传递:适用于可选参数或动态内存管理

void processOptionalData(int* data);  // 可选参数
void allocateMemory(int** ptr);       // 需要修改指针本身

4. 错误处理

输入验证:始终验证函数输入的有效性

double divide(double a, double b) {
    if (b == 0) {
        throw invalid_argument("除数不能为零");
    }
    return a / b;
}

返回值检查:检查函数的返回值以确保操作成功

bool readFile(const string& filename, vector<string>& content) {
    ifstream file(filename);
    if (!file.is_open()) {
        return false;  // 文件打开失败
    }
    
    string line;
    while (getline(file, line)) {
        content.push_back(line);
    }
    
    return true;  // 读取成功
}

🔧 常见错误与调试

1. 条件语句常见错误

错误1:赋值运算符与比较运算符混淆

// 错误:使用了赋值运算符而不是比较运算符
if (x = 5) {  // 这里总是为真,因为x被赋值为5
    // ...
}

// 正确:使用比较运算符
if (x == 5) {
    // ...
}

错误2:逻辑运算符优先级问题

// 错误:逻辑运算符优先级导致的逻辑错误
if (age > 18 && age < 65 || isStudent) {
    // 实际等价于:(age > 18 && age < 65) || isStudent
    // ...
}

// 正确:使用括号明确优先级
if ((age > 18 && age < 65) || isStudent) {
    // ...
}

2. 循环语句常见错误

错误1:数组越界访问

// 错误:循环条件导致数组越界
int arr[10];
for (int i = 0; i <= 10; i++) {  // 应该是 i < 10
    arr[i] = i;  // 当i=10时越界
}

// 正确:正确的循环条件
for (int i = 0; i < 10; i++) {
    arr[i] = i;
}

错误2:无限循环

// 错误:忘记更新循环变量
int i = 0;
while (i < 10) {
    cout << i << endl;
    // 忘记i++,导致无限循环
}

// 正确:记得更新循环变量
int i = 0;
while (i < 10) {
    cout << i << endl;
    i++;
}

3. 函数相关错误

错误1:函数声明与定义不匹配

// 声明
int add(int a, int b);

// 错误:定义与声明不匹配
double add(int a, int b) {  // 返回类型不匹配
    return a + b;
}

// 正确:定义与声明匹配
int add(int a, int b) {
    return a + b;
}

错误2:返回局部变量的引用或指针

// 错误:返回局部变量的引用
int& getValue() {
    int value = 42;  // 局部变量
    return value;    // 返回局部变量的引用(悬垂引用)
}

// 正确:返回值而不是引用
int getValue() {
    int value = 42;
    return value;    // 返回值的副本
}

4. 调试技巧

使用调试输出

void debugFunction(const string& message, int value) {
    #ifdef DEBUG
    cout << "[DEBUG] " << message << ": " << value << endl;
    #endif
}

// 使用示例
debugFunction("循环变量i", i);

断点调试

  • 在关键位置设置断点
  • 检查变量的值和状态
  • 单步执行代码,观察执行流程

日志记录

void logMessage(const string& level, const string& message) {
    ofstream logFile("debug.log", ios::app);
    if (logFile.is_open()) {
        auto now = chrono::system_clock::now();
        auto time_t = chrono::system_clock::to_time_t(now);
        logFile << "[" << put_time(localtime(&time_t), "%Y-%m-%d %H:%M:%S") << "] "
                << "[" << level << "] " << message << endl;
        logFile.close();
    }
}

📖 练习题目

基础练习

练习1:成绩等级判断
编写一个程序,根据输入的成绩输出相应的等级:

  • 90-100分:优秀
  • 80-89分:良好
  • 70-79分:中等
  • 60-69分:及格
  • 60分以下:不及格

练习2:素数判断
编写一个函数,判断一个正整数是否为素数。

练习3:数组排序
编写一个函数,使用冒泡排序算法对整数数组进行排序。

进阶练习

练习4:递归函数练习

  1. 编写递归函数计算第n个斐波那契数
  2. 编写递归函数实现二分查找
  3. 编写递归函数解决汉诺塔问题

练习5:函数重载练习
编写一组重载函数,实现不同类型的数据求和:

  1. 两个整数求和
  2. 三个整数求和
  3. 两个浮点数求和
  4. 数组元素求和

综合练习

练习6:文本分析器
编写一个程序,分析文本文件中的单词频率:

  1. 读取文本文件
  2. 统计每个单词的出现次数
  3. 按频率排序输出结果
  4. 提供查询功能

练习7:简单计算器
扩展本章的计算器功能,增加:

  1. 支持更多数学函数(sin, cos, tan, log等)
  2. 支持表达式计算
  3. 支持变量定义和使用
  4. 支持历史记录功能

📚 参考资源

在线资源

  1. C++官方文档

  2. 学习平台

  3. 社区论坛

推荐书籍

  1. 《C++ Primer》 - Stanley B. Lippman

    • 全面介绍C++语言特性
    • 适合初学者和中级开发者
  2. 《Effective C++》 - Scott Meyers

    • C++编程最佳实践
    • 提高代码质量和性能
  3. 《C++编程思想》 - Bruce Eckel

    • 深入理解C++编程思想
    • 面向对象编程详解

开发工具

  1. 编译器

    • GCC/G++ - GNU编译器套件
    • Clang - LLVM编译器
    • MSVC - Microsoft Visual C++
  2. 调试工具

    • GDB - GNU调试器
    • LLDB - LLVM调试器
    • Visual Studio Debugger
  3. 性能分析

    • Valgrind - 内存检测工具
    • gprof - 性能分析工具
    • Intel VTune - 性能优化工具

📝 本章小结

本章我们深入学习了C/C++中的控制结构和函数,这是构建复杂程序的基础。通过本章的学习,你应该掌握了:

  1. 控制结构的使用:条件语句、循环语句和跳转语句的正确使用方法
  2. 函数的设计与实现:函数定义、参数传递、返回值处理等核心概念
  3. 模块化编程思想:如何将复杂问题分解为可管理的函数模块
  4. 递归编程:理解和实现递归函数来解决复杂问题
  5. 代码组织能力:编写结构清晰、易于维护的程序代码

通过智能游戏中心项目,我们实践了如何综合运用这些知识来构建一个功能完整的应用程序。这个项目展示了控制结构和函数在实际编程中的重要作用。

在下一章中,我们将学习数组和字符串处理,进一步扩展我们的编程能力。


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐