函数定义、调用、参数、返回值全部用进一个完整程序。
我们分四步搭这个计算器:先跑通一种运算,再补齐另外三个函数,
然后加上运算符分支,最后处理除以 0 这种意外情况。
函数定义、调用、参数、返回值全部用进一个完整程序。
我们分四步搭这个计算器:先跑通一种运算,再补齐另外三个函数,
然后加上运算符分支,最后处理除以 0 这种意外情况。
第 11 讲:函数的定义与调用,用参数让函数按不同数据办事, 分清形参与实参。
第 12 讲:返回值,让函数不只是做事,还能把算出来的结果交回调用处, 供后续计算使用。
今天把两者拼在一起,做一个真正有用的小工具——四则运算计算器。
+ - * / 四种运算,各自封装成一个函数。0,提示错误,不进行运算。3 + 4 = 7。直接把四个运算符、四个函数、除零校验全部一次写完,很容易中途出错还不知道错在哪。 更稳妥的办法是:先只实现加法,确认“输入两个数 → 调用函数 → 输出结果” 这条链路能跑通,再一步步往上加。
#include <iostream>
double add(double a, double b) {
return a + b;
}
int main() {
double num1, num2;
std::cout << "请输入第一个数:";
std::cin >> num1;
std::cout << "请输入第二个数:";
std::cin >> num2;
double result = add(num1, num2);
std::cout << num1 << " + " << num2 << " = " << result << std::endl;
return 0;
}
把 calculator_step1.cpp 跑起来,输入几组数字,确认加法结果正确。
确认没问题后,再往下看怎么扩展成完整计算器。
加法能跑通,减乘除照着同样的样子各写一个函数就行——参数一样是两个
double,函数体里换成对应的运算符:
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;
}
四个函数各自逻辑很简单,封装成函数的好处不在“省代码”,而在于让
main 只关心“该调用哪个函数”,不用把具体计算和输入输出交互揉在一起。
运算符用 char 类型的变量 op 接收,再用模块二的
if / else if 多分支,根据 op 的值决定调用哪个函数:
char op;
std::cin >> op;
if (op == '+') {
result = add(num1, num2);
} else if (op == '-') {
result = subtract(num1, num2);
} else if (op == '*') {
result = multiply(num1, num2);
} else if (op == '/') {
result = divide(num1, num2);
} else {
std::cout << "错误:不支持的运算符" << std::endl;
}
这是骨架,还差一件事——除法万一遇到除数 0 怎么办?下一步专门处理。
除以 0 的校验放在main 里、调用 divide
之前——函数只管“怎么算”,“能不能算”这件事交给主流程判断。
再用一个 bool valid 标记,记录这次输入到底能不能算出结果。
这是为了突出本课主流程而采用的简化设计,并不是唯一的组织方式。在更大的程序里,
还要考虑怎样让 divide 本身不会被其他调用者错误地用于除以 0。
#include <iostream>
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 main() {
double num1, num2;
char op;
std::cout << "请输入第一个数:";
std::cin >> num1;
std::cout << "请输入运算符(+ - * /):";
std::cin >> op;
std::cout << "请输入第二个数:";
std::cin >> num2;
double result;
bool valid = true;
if (op == '+') {
result = add(num1, num2);
} else if (op == '-') {
result = subtract(num1, num2);
} else if (op == '*') {
result = multiply(num1, num2);
} else if (op == '/') {
if (num2 == 0) {
std::cout << "错误:除数不能为 0" << std::endl;
valid = false;
} else {
result = divide(num1, num2);
}
} else {
std::cout << "错误:不支持的运算符" << std::endl;
valid = false;
}
if (valid) {
std::cout << num1 << " " << op << " " << num2 << " = " << result << std::endl;
}
return 0;
} main 里没有直接执行加减乘除计算,而是把计算委托给四个函数——
这正是“用函数组织代码”的意义:main 只管流程(读输入 → 选分支 → 调函数 → 输出),
“怎么算”交给函数负责。
valid 这个标记记录“这次输入是否可以算出结果”——除数为 0 或运算符不支持时都设成
false,最后用 if (valid) 决定要不要打印结果,这和第 10 讲猜数字游戏里
win 标记的思路是一样的。
num2 是 double。第 7 讲练习里提到过浮点数比较的坑——
如果 num2 是运算得来的 0.0000001 这种“几乎是 0”的值,
这里的判断还成立吗?这节课先不深究,记住这是个待挖的坑就好。
跑起来,依次测试下面的输入组合,确认输出符合预期:
| 输入 | 期望输出 |
|---|---|
| 3 + 4 | 3 + 4 = 7 |
| 10 - 4 | 10 - 4 = 6 |
| 6 * 7 | 6 * 7 = 42 |
| 7 / 2 | 7 / 2 = 3.5 |
| 5 / 0 | 错误:除数不能为 0 |
| 3 ^ 4 | 错误:不支持的运算符 |
算完结果后,再多打印一行:根据 result 的正负,提示“结果是正数”
“结果是负数”或“结果是零”。
提示:不需要新函数,在 main 里加一段 if / else 就够了。
写一个 bool isValidOperator(char op),返回这个运算符是否是
+ - * / 之一。main 里先调用它判断,再进入运算分支。
写一个函数 power(double base, int exp),用循环算出 base
的 exp 次方,把运算符 ^ 接进 main 的分支里。
本练习只处理 exp >= 0 的整数。
提示:累乘器从 1 开始,循环 exp 次;因此
exp == 0 时不进入循环,结果正好是 1。
给整个计算流程套一层外层循环:算完一次,提示“输入 y 继续,其它任意键退出”, 直到用户选择退出为止。
for
还是 while?回到第 9 讲的挑选标准。
| 讲次 | 核心内容 |
|---|---|
| 第 11 讲 | 函数定义与调用、参数、形参 / 实参 |
| 第 12 讲 | 返回值 return、返回值参与运算 |
| 第 13 讲 | 综合实战:四个函数 + 主流程调度 |
到这里,程序已经能判断、能重复、还能把逻辑 拆分成一个个函数——这是写更大程序必备的组织能力。
vector,
批量存储和处理数据。