一、函数
(一)函数的定义
- 函数定义的格式:
返回值类型 函数名 (形式参数列表)
{
函数体;
返回值;
}
(二)函数的调用
- 无返回值函数的调用:函数名(实际参数列表);
- 有返回值函数的调用:变量 = 函数名(实际参数列表);
(三)函数的参数
- 复制传参:是将实际参数中的值复制一份,赋值给形式参数,修改形式参数,不影响实参。
- 指针传参:就是将实参的地址传递给形参,
- 指针函数:一个函数,其返回值类型是一个指针,
(四)指针函数
- 指针函数:一个函数其返回值类型是一个指针。
char * func(char *s)
{
char a[] = "hello";
printf("%s\n",s);
//return s;
return a;
}
- main的完整形态:
int main(int argc,char *argv[])
{
return 0;
}
//argc 命令行参数个数
//argv 字符串指针数组 存放命令行中的每一个参数,该数组中,有一个NULL 结尾
(五)函数指针
- 函数指针:函数指针是一个指针变量,存放的是一个函数的
- 函数的入口地址:一个函数,在编译为一个机器码指令快的时候,其指令是连续紧挨着的,运行时会存放在代码段中,每一个函数的第一条指令的内存地址,即函数入口地址。
- 函数名:
- 代指这个函数
- 代指函数的入口地址
- 函数指针的定义:
- 函数类型:将函数名,形参名去掉,剩下的即函数类型。
- 函数指针的定义:函数返回值类型 (*指针名) (形参列表) = 函数名。
- 函数指针数组:
#include <stdio.h>
int func1(int a)
{
printf("in %s a=%d\n", __FUNCTION__,a);
return 0;
}
int func2(int a)
{
printf("in %s a=%d\n", __FUNCTION__,a);
return 0;
}
int func3(int a)
{
printf("in %s a=%d\n", __FUNCTION__,a);
return 0;
}
int func4(int a)
{
printf("in %s a=%d\n", __FUNCTION__,a);
return 0;
}
int main()
{
//定义一个函数指针变量
int (*fp)(int) = func1;
printf("hello!\n");
func1(10);
printf("func=%p\n",func1);
(*fp)(50);
// 了解
printf("函数指针数组\n");
int (*arr[5])(int) ={func1,func2,func3,func4,NULL};
/* // 以指针方式访问数组元素
int (**p1)(int) = arr; // 二级函数指针
while(*p1)
{
(*p1)(10);
p1++;
}
*/
// 以数组方式访问数组元素
for(int i = 0; i < 4;i++)
{
arr[i](i);
}
return 0;
}
(六)回调函数
- 回调函数:一个函数其中参数中有函数指针,称此类型函数为回调函数。
#include <stdio.h>
// 回调函数
void youFunc(int a,void (*f1)(void),void (*f2)(void))
{
if(a >= 0) f1();
else f2();
}
void func1(void)
{
printf("执行操作1\n");
printf("用户定义的一些操作\n");
}
void func2(void)
{
printf("执行操作2\n");
}
int main()
{
youFunc(10,func1,func2);
return 0;
}
(七)递归函数
-
递归函数:一个函数,在实现过程中,存在自己调用自己的情况,通过不断地调用自己将问题规模逐渐向临界靠近,直到达到临界情况,然后层层返回退出。
-
本质:是通过对栈空间的迭代,实现循环的效果,递归及其消耗内存,若递归过深,可能会出现栈溢出,报段错误。
-
练习1:用递归求1~100的整数和。
//s(n+1) = S(n) + a(n); // 递推式
//s(n) = S(n-1) + a(n-1);
//s(n-1) = S(n-2) + a(n-2);
//....
//n = 1; s(1) = 1; // 临界情况
#include <stdio.h>
int diguisumfunc(int a);
int main()
{
printf("%d\n",diguisumfunc(100));
return 0;
}
int diguisumfunc(int a)
{
if(a == 1)
{
return 1;
}
return a + diguisumfunc(a-1);
}
练习2:使用递归求解斐波拉契数的第n项。
#include <stdio.h>
int diguifeibolaqi(int n);
int main()
{
int n;
printf("请输入要求的第n个斐波拉契数:\n");
scanf("%d",&n);
printf("第%d个斐波拉契数是:%d\n",n,diguifeibolaqi(n));
return 0;
}
int diguifeibolaqi(int n)
{
if(n == 1 || n == 2)
{
return 1;
}
return diguifeibolaqi(n-1) + diguifeibolaqi(n-2);
}
- 作业1:使用递归求解:
- 猴子吃桃的问题,一天一个猴子摘了许多的桃,第一天吃了一半,忍不住又吃了一个, 第二天又吃了剩下桃的一半,忍不住又多吃了一个,往后每天如此,直到第十天发现只剩下 一个桃了,编程求出猴子第一天一共摘了多少个桃?
#include <stdio.h>
int peach(int day);
int main()
{
int day = 10;
printf("第一天一共摘了%d个桃子。\n",peach(day));
return 0;
}
int peach(int day)
{
if(day == 1)
{
return 1;
}
return 2*(1+peach(day-1));
}
- 杨辉三角:求给定行列的值是多少?
#include <stdio.h>
int yanghuisanjiao(int row,int column);
void printyanghuisanjiao(int row,int column);
int main()
{
int row ,column;
input:
printf("请输入行和列的值:");
scanf("%d %d",&row,&column);
if(column > row)
{
printf("你输入的列的值不应大于行的值\n");
goto input;
}
printyanghuisanjiao(row,column);
return 0;
}
//计算杨辉三角每个位置上的值
int yanghuisanjiao(int row,int column)
{
if(column == 1 || row == column)
{
return 1;
}
return yanghuisanjiao(row - 1, column) + yanghuisanjiao(row - 1,column - 1);
}
//打印杨辉三角
void printyanghuisanjiao(int row,int column)
{
printf("开始打印\n");
for(int i = 1; i <= row; i++)
{
for(int j = 1; j <= i; j++)
{
printf("%-2d ",yanghuisanjiao(i,j));
}
printf("\n");
}
//打印杨辉三角指定位置的值
printf("第%d行,第%d列的值是:%d\n",row,column,yanghuisanjiao(row,column));
}
- 使用递归函数,实现选择排序