H慧博算法实验室
课程中心›2 C++ 程序设计基础›2.12

LESSON 2.12 · 公开免费

2.12 函数入门——把程序拆成小工具

课程正文由飞书云文档同步,并使用慧博算法实验室的教学样式呈现。

☁ 飞书内容源🔄 自动更新
🤖准备开始学习看、想、写、测、改

MISSION · 本课任务

当程序越来越长时,如果把所有代码都写在 main() 中,程序会变得难以阅读,也不方便重复使用。

函数可以把一段具有特定功能的代码包装成一个小工具。

学完本课,你将能够:

✅ 理解函数的作用 ✅ 定义并调用自己的函数 ✅ 理解参数和返回值 ✅ 认识 int、double、bool 和 void 函数 ✅ 理解函数声明与函数定义 ✅ 使用 min、max、abs、sqrt 和 pow ✅ 使用 sort 对数组和 vector 排序 ✅ 使用函数解决具体问题


1 函数是什么

想象我们有一台果汁机:

CODE
放入水果 → 启动机器 → 得到果汁

函数的工作过程也很相似:

CODE
传入数据 → 执行代码 → 返回结果

例如,我们想计算两个整数的和,可以创建一个函数:

CODE
int add(int a, int b) {
    int result = a + b;
    return result;
}

这个函数叫作 add。

它的作用是:

接收两个整数,计算它们的和,并把结果返回。

完整程序:

C++
#include <iostream>
using namespace std;

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

int main() {
    int answer = add(10, 20);

    cout << answer;

    return 0;
}

输出:

CODE
30

其中:

CODE
add(10, 20)

表示调用 add 函数。

程序会进入函数:

CODE
int add(int a, int b)

把:

CODE
10交给a
20交给b

然后计算:

CODE
a + b

最后通过:

CODE
return result;

把结果返回给 main()。


2 函数的基本结构

一个普通函数通常包含四个部分:

CODE
返回值类型 函数名称(参数列表) {
    函数中的代码
    return 返回结果;
}

例如:

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

返回值类型

CODE
int

表示这个函数执行结束后,会返回一个整数。

函数名称

CODE
add

函数名称用于调用函数。

函数名称应该尽量体现它的作用,例如:

CODE
add
getMax
isEven
calculateArea
printMessage

参数列表

CODE
int a, int b

参数是函数接收的数据。

这个函数需要接收两个整数,所以有两个参数。

函数体

CODE
{
    return a + b;
}

大括号中的内容是调用函数时真正执行的代码。

返回结果

CODE
return a + b;

return 会把结果交回调用函数的位置,同时结束当前函数。


3 参数和返回值

什么是参数

参数是调用函数时交给函数的数据。

定义函数:

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

调用函数:

CODE
int result = add(8, 5);

调用时:

CODE
8传给参数a
5传给参数b

所以函数计算:

CODE
8 + 5 = 13

最终:

CODE
result

中保存13。

形参与实参

函数定义中的参数:

CODE
int add(int a, int b)

这里的 a 和 b 叫作形式参数,简称形参。

调用函数时传入的数据:

CODE
add(8, 5)

这里的 8 和 5 叫作实际参数,简称实参。

可以简单理解为:

形参是函数准备好的接收位置,实参是调用时真正传进去的数据。

参数的数量要对应

函数需要两个参数:

CODE
int add(int a, int b)

正确调用:

CODE
add(10, 20);

错误调用:

CODE
add(10);
add(10, 20, 30);

参数类型要合适

函数要求两个整数:

CODE
int add(int a, int b)

调用时通常也应该传入整数:

CODE
add(3, 7);

也可以传入整数变量:

C++
int x = 3;
int y = 7;

cout << add(x, y);

返回值可以直接使用

C++
cout << add(10, 20);

也可以参与运算:

CODE
int result = add(10, 20) * 2;

还可以作为另一个函数的参数:

C++
cout << max(add(3, 5), 6);

先计算:

CODE
add(3, 5)

得到8,再计算:

CODE
max(8, 6)

最后得到8。


4 不同类型的函数

函数前面的类型表示函数返回什么样的数据。

返回整数的函数

CODE
int square(int x) {
    return x * x;
}

调用:

C++
cout << square(6);

输出:

CODE
36

返回小数的函数

计算圆的面积:

CODE
double circleArea(double radius) {
    return 3.1415926 * radius * radius;
}

调用:

C++
double area = circleArea(5.0);

cout << area;

函数返回小数,所以返回值类型是:

CODE
double

返回真假的函数

判断一个整数是不是偶数:

CODE
bool isEven(int x) {
    return x % 2 == 0;
}

调用:

C++
if (isEven(8)) {
    cout << "8是偶数";
}

因为:

CODE
8 % 2 == 0

结果为真,所以函数返回 true。

判断奇数:

CODE
bool isOdd(int x) {
    return x % 2 != 0;
}

判断是否及格:

CODE
bool isPassed(int score) {
    return score >= 60;
}

bool 函数经常用来回答:

CODE
是不是?
有没有?
能不能?

因此,函数名称经常以 is、has、can 开头。


不返回结果的函数

有些函数只负责完成一件事,不需要返回数据。

例如,输出一条分隔线:

C++
void printLine() {
    cout << "--------------------" << endl;
}

调用:

CODE
printLine();

void 表示:

这个函数不返回结果。

再例如:

C++
void sayHello(string name) {
    cout << "你好," << name << "!" << endl;
}

调用:

CODE
sayHello("Alice");
sayHello("Tom");

输出:

CODE
你好,Alice!
你好,Tom!

常见函数类型

返回整数:

CODE
int

返回小数:

CODE
double

返回字符:

CODE
char

返回字符串:

C++
string

返回真假:

CODE
bool

不返回结果:

CODE
void

5 函数的位置、声明与变量范围

函数通常写在main前面

C++
#include <iostream>
using namespace std;

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

int main() {
    cout << add(3, 5);

    return 0;
}

编译器按照从上到下的顺序阅读程序。

当它在 main() 中看到:

CODE
add(3, 5)

它已经在前面见过 add 函数,因此知道如何调用。

函数也可以写在main后面

如果想把函数定义写在 main() 后面,需要先进行函数声明:

C++
#include <iostream>
using namespace std;

int add(int a, int b);

int main() {
    cout << add(3, 5);

    return 0;
}

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

这一行:

CODE
int add(int a, int b);

叫作函数声明。

它提前告诉编译器:

CODE
后面有一个名叫add的函数
它接收两个整数
它会返回一个整数

注意,函数声明的末尾有分号:

CODE
int add(int a, int b);

函数定义的末尾没有分号:

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

函数中的局部变量

观察:

CODE
int add(int a, int b) {
    int result = a + b;

    return result;
}

其中:

CODE
a
b
result

都只属于 add 函数。

在 main() 中不能直接使用:

C++
cout << result;

这种只在某个函数内部有效的变量叫作局部变量。

不同函数中可以出现同名变量:

CODE
int add(int a, int b) {
    int result = a + b;
    return result;
}

int multiply(int a, int b) {
    int result = a * b;
    return result;
}

两个 result 分别属于不同的函数,不会互相影响。


6 C++常用工具函数

C++已经为我们准备了许多常用函数,不需要每次都自己编写。

min和max

使用头文件:

C++
#include <algorithm>

求两个数的较小值:

C++
cout << min(8, 5);

输出:

CODE
5

求两个数的较大值:

C++
cout << max(8, 5);

输出:

CODE
8

也可以使用变量:

CODE
int a = 20;
int b = 35;

int smaller = min(a, b);
int larger = max(a, b);

应用:限制游戏角色的生命值不能超过100。

CODE
int health = 120;

health = min(health, 100);

结果:

CODE
health = 100

应用:保证分数不能低于0。

CODE
int score = -5;

score = max(score, 0);

结果:

CODE
score = 0

abs绝对值

绝对值表示一个数到0的距离。

C++
cout << abs(-8);

输出:

CODE
8
C++
cout << abs(5);

输出:

CODE
5

应用:计算两个数之间相差多少。

C++
int a = 15;
int b = 9;

cout << abs(a - b);

输出:

CODE
6

因为无论:

CODE
a - b

是正数还是负数,绝对值都会得到非负结果。


sqrt平方根

使用头文件:

C++
#include <cmath>

计算平方根:

C++
cout << sqrt(81);

输出:

CODE
9

再例如:

C++
double result = sqrt(2);

cout << result;

sqrt(2) 的结果是一个小数。

注意:

sqrt(x) 中的 x 应该大于或等于0。


pow乘方

计算2的10次方:

C++
cout << pow(2, 10);

输出:

CODE
1024

其中:

CODE
pow(a, b)

表示计算:

CODE
a的b次方

例如:

CODE
pow(3, 2)

表示:

CODE
3² = 9

计算平方时,也可以直接写:

CODE
x * x

对于简单的整数平方,x∗xx * x 通常更加直观。


sort排序

使用头文件:

C++
#include <algorithm>

sort 可以把数据按照从小到大的顺序排列。

对普通数组排序:

CODE
int a[5] = {8, 3, 10, 2, 6};

sort(a, a + 5);

排序后:

CODE
2 3 6 8 10

输出:

C++
for (int i = 0; i < 5; i++) {
    cout << a[i] << " ";
}

其中:

CODE
sort(a, a + 5);

表示排序的范围是:

CODE
从a[0]开始,到a[5]之前结束

也就是排序:

CODE
a[0]~a[4]

如果实际输入了 n 个元素:

CODE
sort(a, a + n);

对vector排序

C++
vector<int> a = {8, 3, 10, 2, 6};

sort(a.begin(), a.end());

排序后:

CODE
2 3 6 8 10

其中:

CODE
a.begin()

表示第一个元素的位置。

CODE
a.end()

表示最后一个元素之后的位置。

从大到小排序

CODE
sort(a.begin(), a.end(), greater<int>());

需要包含:

C++
#include <functional>

排序结果:

CODE
10 8 6 3 2

7 使用函数解决具体问题

问题一:计算两点之间的距离

平面上有两个点:

CODE
A(x₁, y₁)
B(x₂, y₂)

两点之间的距离公式是:

CODE
√((x₁-x₂)²+(y₁-y₂)²)

可以把这个计算过程包装成函数:

CODE
double pointDistance(int x1, int y1, int x2, int y2) {
    int dx = x1 - x2;
    int dy = y1 - y2;

    return sqrt(dx * dx + dy * dy);
}

完整程序:

C++
#include <iostream>
#include <cmath>
using namespace std;

double pointDistance(int x1, int y1, int x2, int y2) {
    int dx = x1 - x2;
    int dy = y1 - y2;

    return sqrt(dx * dx + dy * dy);
}

int main() {
    int x1, y1;
    int x2, y2;

    cin >> x1 >> y1;
    cin >> x2 >> y2;

    cout << pointDistance(x1, y1, x2, y2);

    return 0;
}

输入:

CODE
0 0
3 4

输出:

CODE
5

使用函数后,main() 中不需要关心距离公式的具体细节。

只需要调用:

CODE
pointDistance(x1, y1, x2, y2)

问题二:判断一个数是否为偶数

创建判断函数:

CODE
bool isEven(int x) {
    return x % 2 == 0;
}

完整程序:

C++
#include <iostream>
using namespace std;

bool isEven(int x) {
    return x % 2 == 0;
}

int main() {
    int n;
    cin >> n;

    if (isEven(n)) {
        cout << "偶数";
    } else {
        cout << "奇数";
    }

    return 0;
}

这个程序把任务分成了两部分:

CODE
isEven函数:负责判断
main函数:负责输入和输出

问题三:数组排序后寻找最值

输入 n 个整数,将它们从小到大排列,然后输出最小值、最大值和排序后的数组。

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void printVector(vector<int> a) {
    for (int i = 0; i < a.size(); i++) {
        cout << a[i] << " ";
    }

    cout << endl;
}

int main() {
    int n;
    cin >> n;

    vector<int> a(n);

    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    sort(a.begin(), a.end());

    cout << "最小值:" << a.front() << endl;
    cout << "最大值:" << a.back() << endl;
    cout << "排序结果:";

    printVector(a);

    return 0;
}

输入:

CODE
5
8 3 10 2 6

输出:

CODE
最小值:2
最大值:10
排序结果:2 3 6 8 10

这里:

CODE
sort(a.begin(), a.end());

负责排序。

CODE
printVector(a);

负责输出整个 vector。

不同的函数分别完成不同的任务,程序结构会更加清晰。


问题四:找到最接近目标的数字

输入若干整数和一个目标值,找到与目标值相差最小的数字。

例如:

CODE
数组:3 12 18 25 30
目标:20

每个数字与20的距离:

CODE
|3-20|  = 17
|12-20| = 8
|18-20| = 2
|25-20| = 5
|30-20| = 10

所以最接近20的是18。

参考程序:

C++
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

int main() {
    int n, target;
    cin >> n >> target;

    vector<int> a(n);

    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    int answer = a[0];
    int minDistance = abs(a[0] - target);

    for (int i = 1; i < n; i++) {
        int currentDistance = abs(a[i] - target);

        if (currentDistance < minDistance) {
            minDistance = currentDistance;
            answer = a[i];
        }
    }

    cout << answer;

    return 0;
}

这个问题中,abs() 帮助我们计算两个数字之间的距离。


8 常见错误与本课小结

错误一:函数声明和调用不一致

定义:

CODE
int add(int a, int b)

错误调用:

CODE
add(10);

函数需要两个参数,调用时也要传入两个参数。


错误二:返回值类型与结果不合适

CODE
int average(int a, int b) {
    return (a + b) / 2.0;
}

函数返回的是小数,但类型写成了 int,小数部分会丢失。

应该写成:

CODE
double average(int a, int b) {
    return (a + b) / 2.0;
}

错误三:有返回值的函数忘记return

错误:

CODE
int square(int x) {
    int result = x * x;
}

正确:

CODE
int square(int x) {
    int result = x * x;

    return result;
}

错误四:把函数调用写成函数名称

错误:

C++
cout << square;

正确:

C++
cout << square(5);

调用函数时需要小括号。


错误五:sort的结束位置写错

错误:

CODE
sort(a, a + n - 1);

这不会包含最后一个元素。

正确:

CODE
sort(a, a + n);

sort 的结束位置指向最后一个元素的后面。


本课工具箱

定义整数函数:

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

定义真假函数:

CODE
bool isEven(int x) {
    return x % 2 == 0;
}

定义无返回值函数:

C++
void printLine() {
    cout << "--------" << endl;
}

调用函数:

CODE
int result = add(3, 5);

常用工具函数:

CODE
min(a, b)
max(a, b)
abs(x)
sqrt(x)
pow(a, b)

普通数组排序:

CODE
sort(a, a + n);

vector 排序:

CODE
sort(a.begin(), a.end());

最重要的认识:

函数是一个可以被反复调用的小工具。 参数是交给函数的数据,返回值是函数计算出的结果。 把大问题拆成多个小函数,程序会更清晰、更容易修改。


CHECKPOINT · 课后检查

  1. 函数有什么作用?
  2. 函数的返回值类型写在什么位置?
  3. 什么是函数的参数?
  4. 形参和实参有什么区别?
  5. return 有什么作用?
  6. int 函数和 double 函数有什么区别?
  7. bool 函数适合解决什么问题?
  8. void 表示什么?
  9. 函数定义写在 main() 后面时,为什么需要函数声明?
  10. 什么是局部变量?
  11. min 和 max 分别有什么作用?
  12. abs 适合解决什么问题?
  13. sqrt(81) 的结果是多少?
  14. pow(2, 10) 表示什么?
  15. 如何对普通数组的前 n 个元素排序?
  16. 如何对整个 vector 排序?
  17. 为什么使用函数后,程序更容易阅读和修改?

编程挑战

编写下面四个函数:

CODE
int getMax(int a, int b);
int getMin(int a, int b);
bool isPositive(int x);
double rectangleArea(double width, double height);

然后在 main() 中输入数据并调用这些函数,分别完成:

  • 求两个整数的最大值;
  • 求两个整数的最小值;
  • 判断一个数是不是正数;
  • 计算长方形的面积。
本课目录 · 点击展开