当前位置: 首页 > article >正文

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;
}

片尾

今天我们学习了函数相关知识,下一篇我们将继续练习函数部分习题。希望看完这篇文章对友友们有所帮助!!!

点赞收藏加关注!!!

谢谢大家!!!


http://www.kler.cn/a/578471.html

相关文章:

  • UE4 World, Level, LevelStreaming从入门到深入
  • 【Linux系统编程】初识系统编程
  • RMAN备份bug-审计日志暴涨(select action from gv$session)
  • ECC升级到S/4 HANA的功能差异 物料、采购、库存管理对比指南
  • 软件网络安全测试用例
  • 【深度学习】Pytorch:更换激活函数
  • docker-compose Install reranker(fastgpt支持) GPU模式
  • 阿里云扩容操作步骤
  • 云效、流水线、Gradle缓存问题、build.gradle配置snapshot
  • 从0开始的操作系统手搓教程28:实现Syscall架构体系
  • 8.大模型微调学习案例:基于 Hugging Face、8位量化与 LoRA 适配器的方案
  • LVS+Nginx接入层架构图
  • 利用FatJar彻底解决Jar包冲突(一)
  • STM32F407 NVIC和外部中断
  • 深度学习分类回归(衣帽数据集)
  • JSAR 基础 1.2.1 基础概念_空间小程序
  • 【Kotlin】Kotlin基础笔记
  • C/C++中使用CopyFile、CopyFileEx原理、用法、区别及分别在哪些场景使用
  • Linux 命令 for循环
  • 【MATLAB例程】二维环境定位,GDOP和CRLB的计算