【Linux C/C++开发】第3章:控制结构与函数
第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 递归的基本要素
- 基本情况(Base Case):递归终止的条件
- 递归情况(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个盘子从辅助柱移到目标柱
}
}
💻 实践项目:智能游戏中心
项目概述
我们将创建一个综合性的游戏中心,集成多个经典游戏和实用工具,全面展示控制结构和函数的应用。
功能特性
- 主菜单系统:使用switch-case实现游戏选择
- 猜数字游戏:使用循环和条件语句
- 21点游戏:综合运用各种控制结构
- 计算器:函数封装和重载
- 成绩管理:文件操作和数据处理
- 系统设置:参数配置和状态管理
完整代码实现
#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:递归函数练习
- 编写递归函数计算第n个斐波那契数
- 编写递归函数实现二分查找
- 编写递归函数解决汉诺塔问题
练习5:函数重载练习
编写一组重载函数,实现不同类型的数据求和:
- 两个整数求和
- 三个整数求和
- 两个浮点数求和
- 数组元素求和
综合练习
练习6:文本分析器
编写一个程序,分析文本文件中的单词频率:
- 读取文本文件
- 统计每个单词的出现次数
- 按频率排序输出结果
- 提供查询功能
练习7:简单计算器
扩展本章的计算器功能,增加:
- 支持更多数学函数(sin, cos, tan, log等)
- 支持表达式计算
- 支持变量定义和使用
- 支持历史记录功能
📚 参考资源
在线资源
-
C++官方文档
-
学习平台
- LeetCode - 算法练习
- HackerRank - C++编程挑战
- Codeforces - 竞赛编程
-
社区论坛
- Stack Overflow - 技术问答
- Reddit r/cpp - C++社区讨论
推荐书籍
-
《C++ Primer》 - Stanley B. Lippman
- 全面介绍C++语言特性
- 适合初学者和中级开发者
-
《Effective C++》 - Scott Meyers
- C++编程最佳实践
- 提高代码质量和性能
-
《C++编程思想》 - Bruce Eckel
- 深入理解C++编程思想
- 面向对象编程详解
开发工具
-
编译器
- GCC/G++ - GNU编译器套件
- Clang - LLVM编译器
- MSVC - Microsoft Visual C++
-
调试工具
- GDB - GNU调试器
- LLDB - LLVM调试器
- Visual Studio Debugger
-
性能分析
- Valgrind - 内存检测工具
- gprof - 性能分析工具
- Intel VTune - 性能优化工具
📝 本章小结
本章我们深入学习了C/C++中的控制结构和函数,这是构建复杂程序的基础。通过本章的学习,你应该掌握了:
- 控制结构的使用:条件语句、循环语句和跳转语句的正确使用方法
- 函数的设计与实现:函数定义、参数传递、返回值处理等核心概念
- 模块化编程思想:如何将复杂问题分解为可管理的函数模块
- 递归编程:理解和实现递归函数来解决复杂问题
- 代码组织能力:编写结构清晰、易于维护的程序代码
通过智能游戏中心项目,我们实践了如何综合运用这些知识来构建一个功能完整的应用程序。这个项目展示了控制结构和函数在实际编程中的重要作用。
在下一章中,我们将学习数组和字符串处理,进一步扩展我们的编程能力。
更多推荐


所有评论(0)