C++蓝桥杯基础篇(九)
片头
嗨!小伙伴们,大家好~ 今天我们将学习蓝桥杯基础篇(十),学习函数相关知识,准备好了吗?咱们开始咯!
一、函数基础
一个典型的函数定义包括以下部分:返回类型、函数名字、由0个或多个形参组成的列表以及函数体。
1.1 编写函数
我们来编写一个求阶乘的程序,程序如下所示:
int fact(int val) {
int ret = 1;
int i = 1;
while (i <= val) {
ret *= i;
i++;
}
return ret;
}
函数名字是fact,它作用于一个整型参数,返回一个整型值,return语句负责结束fact并返回ret的值。
1.2 调用函数
int main() {
int t = fact(5);
cout <<"5的阶乘为: " << t << endl;
return 0;
}
函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给被调用函数。此时,主调函数的执行被暂时中断,被调函数开始执行。
1.3 形参和实参
实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推。形参和实参的类型和个数必须匹配。
fact("hello"); //错误: 实参类型不正确
fact(); //错误: 实参数量不足
fact(42, 10, 0); //错误: 实参数量过多
fact(3.14); //正确: 该实参能转换成int类型,等价于fact(3);
形参也可以设置默认值,但所有默认值必须是最后几个。当传入的实参个数少于形参个数时,最后没有被传入值的形参会使用默认值。
1.4 函数的形参列表
函数的形参列表可以为空,但是不能省略。
void f1(){/*...*/ } //隐式地定义空形参列表
void f2(void) {/*...*/ } //显示地定义空形参列表
形参列表中的形参通常用逗号隔开,其中每个形参都是含有一个声明符的声明。即使2个形参的类型一样,也必须把2个类型都写出来:
int f3(int v1,v2){/*...*/ } //错误
int f4(int v1,int v2){/*...*/ } //正确
1.5 函数返回类型
大多数类型都能用作函数的返回类型,比如:int、double、char、bool...。一种特殊的返回类型是void,它表示函数不返回任何值。函数的返回类型不能是数组类型或函数类型,但可以是指向数组或者函数的指针。
1.6 局部变量、全局变量与静态变量
局部变量只可以在函数内部使用,全局变量可以在所有函数内使用。当局部变量与全局变量重名时,会优先使用局部变量。
二、参数传递
2.1 传值参数
当初始化一个非引用类型的变量时,初始值被拷贝给变量。此时,对变量的改变不会影响初始值。
2.2 传引用参数
当函数的形参为引用类型时,对形参的修改会影响实参的值。使用引用的作用:避免拷贝、让函数返回额外的信息。
int max(int& x, int& y) {
x = 10, y = 20;
if (x > y) return x;
return y;
}
int main() {
int a, b;
cout << "请输入a,b的值:";
cin >> a >> b;
cout << "max(a, b)函数的返回值为: " << max(a, b) << endl;
cout << "新的a,b的值为: " << a << " " << b << endl;
return 0;
}
咱们的交换函数swap也可以用带有引用&的参数来实现:
//交换函数
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
2.3 数组形参
在函数中对数组中的值的修改,会影响函数外面的数组
一维数组形参的写法
//尽管形式不同,但这3个printf函数是等价的
void print(int* a){/*...*/ }
void print(int a[]){/*...*/}
void print(int a[10]){/*...*/ }
举一个例子看看吧~
void print(int a[]) {
for (int i = 0; i < 10; i++) {
cout << a[i] << endl;
}
}
int main() {
int a[10];
for (int i = 0; i < 10; i++) {
a[i] = i;
}
print(a);
return 0;
}
多维数组形参的写法:
//多维数组中,除了第一维之外,其余维度的大小必须指定
void print(int (*a)[10]){/*...*/ }
void print(int a[][10]){/*...*/ }
我们同样,举一个例子~
void output(int n, int m, int a[3][3]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int main() {
//定义一个二维数组
int a[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9},
};
//输出这个二维数组
output(3, 3, a);
return 0;
}
注意:当二维数组作为形参的时候,行可以省略,但是列不能省略。当我们在函数中对二位数组中的值进行修改时,相应的二维数组也会发生变化:
void output(int n, int m, int a[][3]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << a[i][j] << " ";
a[i][j] = 1;
}
cout << endl;
}
}
int main() {
int a[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9},
};
output(3, 3, a);
puts("");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}
结果如下:
三、返回类型和return语句
return语句终止当前正在执行的函数并将控制权返回到调用该函数的地方。return 语句有2种形式:
return;
return expression;
3.1 无返回值函数
没有返回值的return语句只能用在返回类型是void的函数中。返回void的函数不要求非得有return语句,因为在这类函数的最后一句后面会隐式地执行return。
通常情况下,返回值为void函数如果想在它的中间位置提前退出,可以使用return语句。return的这种用法有点类似于我们用break语句退出循环。
void swap(int& v1, int& v2) {
//如果2个值相等,则不需要交换,直接退出
if (v1 == v2)
return;
//程序执行到了这里,说明还需要继续完成某些功能
int temp = v2;
v2 = v1;
v1 = temp;
//此处无需显示的return语句
}
3.2 有返回值的函数
只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。return语句返回值的类型必须与函数的返回类型相同,或者能隐式地转换函数的返回类型。
int max(int x, int y) {
if (x > y) return x;
return y;
}
int main() {
int x, y;
cin >> x >> y;
cout << max(x, y) << endl;
return 0;
}
四、函数递归
在一个函数内部,也可以调用函数本身
//用递归实现n!
int fac(int n) {
if (n <= 1) return 1;
return n * fac(n - 1);
}
int main() {
int n;
cin >> n;
cout << fac(n) << endl;
return 0;
}
咱们画个图,好理解一些~
五、练习题
第1题 n的阶乘
代码如下:
//n的阶乘
//输入一个整数n,请你编写一个函数,int fact(int n),计算并输出n的阶乘。
//输入共一行,包含一个整数n。
//输出共一行,包含一个整数表示n的阶乘的值。
//数据范围1≤n < 10
int fact(int n) {
int ret = 1;
int i = 1;
while (i <= n) {
ret *= i;
i++;
}
return ret;
}
int main() {
int n;
cin >> n;
int t = fact(n);
cout << n <<"的阶乘为: " << t << endl;
return 0;
}
第2题 x和y的最大值
代码如下:
//x和y的最大值
//输入两个整数x和y,请你编写一个函数,int max(intx,int y),计算并输出x和y的最大值。
//输入共一行,包含两个整数x和y。
//输出共一行,包含一个整数,表示两个数中较大的那个数。
//数据范围 - 100 ≤x, y≤ 100
int max(int x, int y) {
if (x > y) return x;
return y;
}
int main() {
int x, y;
cin >> x >> y;
int ret = max(x, y);
cout << "两个数中较大的那个数为: " << ret << endl;
return 0;
}
第3题 最大公约数
代码如下:
//最大公约数
//输入两个整数a和b,请你编写一个函数,int gcd(int a,int b),计算并输出a和b的最大公约数。
//输入共一行,包含两个整数a和b。
//输出共一行,包含一个整数,表示a和b的最大公约数。
//数据范围1 ≤ a, b≤ 1000
//输入样例:12 16
//输出样例:4
int gcd(int a, int b) {
for (int i = 1000; i >= 0; i--) {
if (a % i == 0 && b % i == 0) {
return i;
}
}
return -1;
}
int main() {
int a, b;
cin >> a >> b;
int ret = gcd(a, b);
cout << "最大公约数为: " << ret << endl;
return 0;
}
第4题 交换数值
代码如下:
//交换数值
//输入两个整数x和y,请你编写一个函数,void swap(int &x,int &y),交换两个整数的数值并输出交换后的x和y。
//输入共一行,包含两个整数x和y。
//输出共一行,包含交换后的x和y。
//数据范围 1 ≤ x, y≤ 100
//输入样例: 3 5
//输出样例: 5 3
void swap(int& x, int& y) {
if (x == y) return; //如果2个数相等,则不用交换
int t = x; //2个数不相等的情况
x = y;
y = t;
}
int main() {
int x, y;
cout << "交换前: ";
cin >> x >> y;
swap(x, y);
cout << "交换后: ";
cout << x <<" "<< y << endl;
return 0;
}
第5题 打印数字
代码如下:
//打印数字
//输入一个长度为n的数组a和一个整数size,请你编写一个函数,void print(int a[],int size),打印数组a中的前size个数
//输入第一行包含两个整数n和size。
//第二行包含n个整数a[],表示整个数组。
//输出共一行,包含size个整数,表示数组的前size个数。
//数据范围 1 ≤n ≤ 1000 ,1 < size < n,
//输入样例:5 3
// 1 2 3 4 5
//输出样例: 1 2 3
void print(int a[], int size) {
for (int i = 0; i < size; i++) {
cout << a[i] << " ";
}
cout << endl;
}
int main() {
int a[1000];
int n;
cin >> n;
int size;
cin >> size;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
print(a, size);
return 0;
}
第6题 打印矩阵
代码如下:
//打印矩阵
//给定一个row*col的二维数组a,请你编写一个函数,void print2D(int a[][N],int row,int col),打印数组构成的row行,col列的矩阵。
//注意,每打印完一整行需要输出一个回车。
//输入第一行包含两个整数row, col。
//接下来row行,每行包含col个整数,表示完整二维数组a。
//输出共row行,每行col个整数,表示打印出的矩阵。
//数据范围 1 < row < 100, 1 ≤ col < 100
//输入样例: 3 4
// 1 3 4 5
// 2 6 9 4
// 1 4 7 5
//输出样例:
// 1 3 4 5
// 2 6 9 4
// 1 4 7 5
const int N = 100;
int a[N][N] = { 0 };
void print2D(int a[][N], int row, int col) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int main() {
int row, col;
cin >> row >> col;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
cin >> a[i][j];
}
}
print2D(a, row, col);
return 0;
}
第7题 递归求阶乘
代码如下:
//递归求阶乘
//请使用递归的方式求n的阶乘。
//输入共一行,包含一个整数n。
//输出共一行,包含一个整数,表示n的阶乘的值。
//数据范围 1 ≤n≤ 10
//输入样例: 3
//输出样例: 6
int Func(int n) {
if (n == 1) return 1;
return n * Func(n - 1);
}
int main() {
int n;
cin >> n;
int ret = Func(n);
cout << n << "的阶乘为: " << ret << endl;
return 0;
}
第8题 递归求斐波那契数列
代码如下:
//递归求斐波那契数列
//斐波那契数列:1,1,2,3,5..,这个数列从第3项开始,每一项都等于前两项之和
//输入共一行,包含整数n
//输出共一行,包含一个整数,表示斐波那契数列的第n项。
//数据范围 1≤n < 30
//输入样例: 8
//输出样例: 3
//f(1) = 1,f(2) = 1
//f(3) = f(1) + f(2)
//f(4) = f(2) + f(3)
//f(5) = f(3) + f(4)
//f(6) = f(4) + f(5)
//f(7) = f(5) + f(6)
//...
//f(n) = f(n-2) + f(n-1)
int Fab(int n) {
if (n <= 2) return 1;
return Fab(n - 2) + Fab(n - 1);
}
int main() {
int n;
cin >> n;
int ret = Fab(n);
cout << "斐波那契数列的第 " << n << " 项为: " << ret << endl;
return 0;
}
片尾
今天我们学习了函数相关知识,下一篇我们将继续练习函数部分习题。希望看完这篇文章对友友们有所帮助!!!
求点赞收藏加关注!!!
谢谢大家!!!