3.6 常见问题与调试
1 常见错误类型
🧩 返回值错误
情景故事:小明写了一个计算平均分的函数,但总是得到奇怪的结果…
// 有问题的函数
double calculateAverage(int a, int b) {int sum = a + b;sum / 2; // 忘记return啦!
}// 正确写法
double calculateAverage(int a, int b) {return (a + b) / 2.0; // 注意用2.0保证小数运算
}
趣味练习:找出下面函数的错误
string getGrade(int score) {if(score >= 90) "A";else return "B";
}
🔌 参数不匹配
情景故事:小红想用函数画三角形,但总提示错误…
// 函数定义
void drawTriangle(int size, char symbol) { /*...*/ }// 错误调用
drawTriangle('*', 5); // 顺序反了!
记忆口诀:
“参数顺序要记牢,就像穿鞋先穿袜”
🌀 递归栈溢出
情景故事:小刚的递归函数让电脑"卡死"了…
// 危险!没有终止条件
void countDown(int num) {cout << num << endl;countDown(num - 1); // 无限循环!
}// 安全版本
void countDown(int num) {if(num < 0) return; // 停止条件cout << num << endl;countDown(num - 1);
}
可视化理解:
countDown(3)
→ 打印3
→ countDown(2)→ 打印2→ countDown(1)→ 打印1→ countDown(0)→ 打印0→ countDown(-1) ✋停止
2 调试技巧
🖨️ 输出中间值
侦探游戏:像侦探一样收集线索!
int mysteryFunction(int x) {cout << "侦探日志:收到x=" << x << endl; // 线索1int step1 = x * 2;cout << "第一步计算后:" << step1 << endl; // 线索2int result = step1 + 5;cout << "最终结果:" << result << endl; // 线索3return result;
}
实践任务:在下面的函数中添加侦探日志
int calculate(int a, int b) {int sum = a + b;int product = a * b;return sum + product;
}
🧩 分步测试法
积木拆解法:把大问题拆成小积木测试
// 原函数
int complexCalculation(int x) {int a = x * 2;int b = a + 5;int c = b / 3;return c * c;
}// 分步测试
void testSteps() {int testValue = 4;cout << "测试第一步:" << testValue * 2 << endl; // 应得8cout << "测试第二步:" << 8 + 5 << endl; // 应得13// ...继续测试其他步骤
}
📝 纸笔辅助法
画图练习:用纸笔追踪变量变化
void confusingFunction() {int a = 3;a = a + 2;int b = a * 4;a = b - 5;cout << a << "," << b;
}
追踪表格:
行号 | a的值 | b的值 |
---|---|---|
1 | 3 | ? |
2 | 5 | ? |
3 | 5 | 20 |
4 | 15 | 20 |
3 调试练习
🐞 有bug的求和函数
// 这个函数应该计算1+2+...+n
int sumToN(int n) {int sum = 0;for(int i = 1; i <= n; i--) { // 这里有错!sum += i;}return sum;
}
调试任务:
- 用纸笔画出当n=3时的循环过程
- 添加cout输出i和sum的变化
- 找出并修复错误
♾️ 无限递归示例
void countStars(int n) {cout << "*";countStars(n); // 问题出在这里!
}
修复挑战:
- 这个函数会输出多少个星号?
- 如何修改才能让它只输出n个星号?
- 添加什么条件可以防止无限递归?
🔄 参数传递错误案例
void swap(int a, int b) { // 这里有问题!int temp = a;a = b;b = temp;
}int main() {int x = 1, y = 2;swap(x, y);cout << x << "," << y; // 输出什么?
}
思考问题:
- 为什么x和y的值没有交换?
- 如何修改swap函数才能真的交换两个数?
- 画图说明值传递和引用传递的区别
趣味调试游戏
🕵️♂️ 代码侦探社
游戏规则:
- 老师准备5个有bug的代码片段
- 学生分组扮演"代码侦探"
- 每组用学到的调试方法找出bug
- 最快修复所有bug的小组获胜
示例案件:
// 案件1:这个函数应该判断数字是否是偶数
bool isEven(int num) {return num % 2 = 0; // 这里有线索!
}
🧩 调试拼图
将正确代码打印在纸上并剪成碎片,学生需要:
- 先找出代码中的错误
- 然后拼出正确的代码
- 最后用电脑验证
家长辅助指南
家庭调试练习
// 周末家庭任务:帮爸爸妈妈找出购物计算程序的bug
void shopping() {float price = 18.5;int quantity = 3;float total = price * quantity;cout << "总价:" << total << endl;cout << "折扣后:" << total * 0.1 << endl; // 这里有错!
}
亲子互动:
- 预期输出总价是55.5,折扣后应该是50
- 实际输出有什么问题?
- 一起思考如何修正
可视化学习工具推荐
- Python Tutor:可视化代码执行过程
- Code.org调试游戏:适合初学者的互动游戏
- Scratch调试项目:通过积木块理解调试概念
本章总结卡
错误类型 | 常见表现 | 解决方法 |
---|---|---|
忘记返回值 | 得到随机数 | 检查所有路径都有return |
参数顺序错 | 结果不对 | 对照函数定义检查 |
无限递归 | 程序卡死 | 添加终止条件 |
记忆儿歌:
编程出错不要慌,调试技巧来帮忙
输出中间看一看,分步测试不能忘
纸笔追踪变量变,小小bug无处藏
课后实践任务
- 基础题:修复一个计算圆面积的函数(故意去掉π)
- 提高题:找出斐波那契数列函数中的逻辑错误
- 挑战题:调试一个错误的密码验证程序
- 创意题:设计自己的"找bug"游戏关卡
教师提示:可以准备一些贴纸奖励成功调试的学生,培养他们"debug小能手"的成就感!