一、函数
1. 库函数
2. 自定义函数
3. 函数的使用(声明、定义、调用)
4. 函数递归
5. 函数迭代
1.1 为什么有库函数?
* 我们在开发的过程中每个程序员都可能用的到, 为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
1.2 库函数有哪些?
请看以下图片:
简单的总结,C语言常用的库函数都有:
- IO函数
- 字符串操作函数
- 字符操作函数
- 内存操作函数
- 时间/日期函数
- 数学函数
- 其他库函数
(使用库函数必须要引用#include)
2.1 为什么自定义函数?
自定义函数才是让程序员这个职业,有了更大的创造力。
应为不是所有的库函数都可以解决所有的问题的,很多时候还是需要程序员们通过自定义函数去设计代码来完成要的目的。
2.2 什么是自定义函数?
* 自定义函数和库函数一样,有函数名、返回值类型和函数参数。
int add(int x,int y)//这是一个int类型的自定义函数,函数参数是int x,int y
{
int sum = x + y;
return sum;//返还应该int类型的值sum
}
以上就是一个最简单的自定义函数,当然他是有一个有返回值的自定义函数
还有一种是无返回值的自定义函数,请往下看:
void add(int x,int y)//这是一个无返回值的自定义函数,函数参数是int x,int y
{
int sum = x + y;
printf("和为:%d\n",sum);
//所以最后可以不加return
}
这就是自定义函数有无返值的书写大致摸样
2.2.1 函数参数
- 实际参数(实参)
- 真实传给函数的参数,叫实参。
- 实参可以是:常量、变量、表达式、函数等。
- 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。
- 实际参数的储存位置在静态内存区
- 形式参数(形参)
- 形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单元),所以叫形式参数。
- 形式参数当函数调用完成之后就自动销毁了。
- 形式参数只在函数中有效。
- 形式参数的储存位置在栈区
根据上面的实参与形参的了解可以知道,既然两者的储存位置的都不同,那作用肯定也不一样,上代码:以下是一个通过自定义函数来实现交换俩个变量的值
如果知道形式参数的性质的应该就会知道,此时的形式参数其实就是a,b的拷贝数据,完全独立于a,b的值,也就是说此时你在自定义函数add中无论对x,y进行多少次换值或者赋值,都不会影响到a,b,因为当程序从add函数中出来的的时候x,y的值也就销毁了,用时生成,用完销毁,这就是形参。接下来证明我刚刚说的x,y是独立于a,b,请看:
由右上角上的地址看出,x,y和a,b都是地址不同的变量,那么也就证实了我刚刚说的。
如果是这样的话,那么其实这个代码不能完成预期的效果的
请看:
没错,就是应为我刚刚说的他们是或许独立的俩对变量,所以你单单改变x,y是无法使a,b也随之改变的,当然那如果是实参呢?会不会不一样的(这里面会涉及一些指针知识)
请看:
果然成功了,那是不是说明如果将实参传入函数中,可使*x,*y和a,b产生联系,那是不是应为它们的地址也是相同的呢
请看:
由上图可以看出*x,*y和a,b的地址是一样,而在形参中它们是互相独立的,所以这也是为什么它们之间无法影响到对方,在c语言中两个变量拥有同一个地址,那就是说明他们同时指向同一个值,在c语言中是不会有两个相同地址而值不同的变量存在的
以上这种也可以成为传值调用,这是c语言中唯一一种可以交换俩个值的方法
3.1函数的使用
3.1.1 函数的声明
int arr(int x, int y)
这就是函数声明,告诉计算机有这么一个函数,但是到底是不是真的计算机不知道,因为,计算机还没检测到函数的定义。
3.1.2 函数的定义
int arr(int x,int y)
{
int tem = x + y;
return tem;
}
这就是函数的定义,计算机直到这一步才会认为你刚刚那个函数定义是真的
3.1.3 函数调用
#include<stdio.h>
int arr(int, int);//函数声明
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int ch = arr(a, b);//函数调用
printf("%d", ch);
return 0;
}
int arr(int x, int y)//函数定义
{
int tem = x + y;
return tem;
}
3.2 如果没有函数声明可以吗?
不可以,但是在一定条件下,函数定义也是可以充当特殊的函数定义的
更具上面的两张代码图可以看出,函数定义在一定条件下是可以当做特殊的函数声明的
3.3函数的声明、定义、调用,就是怎么用的吗?
当然不是啦,其实函数的声明、定义、调用真正的用法是在以后在团队合作中体现出来的,接下来我可以给演示一个最简单的代码:
ok,这就是函数声明、定义、调用的真正用法
以上代码是将函数声明放在了,头文件里面放了就是函数声明,应为我们都知道函数都是具有全局性的,所有arr.c和test_4_26.c可以建立联系也是可以解释的,所以这就是为了以后的代码工作中分工协作有了更好帮助。
4.1 什么是递归
* 程序调用自身的编程技巧称为递归( recursion)。
* 递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接 调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问 题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程 序的代码量。
* 递归的主要思考方式在于:把大事化小
4.2 递归的俩个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。
这里给俩个递归的运行代码示例:
#include<stdio.h>
void arr(int x)//提取一个整数的每一位数字,并且打印出每一位
{
if (x > 9)//如果x大于9,则说明还有需要在提取数字
{
arr(x / 10);//将x/10这个值在给到arr()函数,让他接着提取前几位的数字
}
printf("%d ", x % 10);//将提取该函数在栈区保存的x的最后一位值,并且打印出来
}
int main()
{
int i = 1234;
arr(i);
return 0;
}
#include<stdio.h>
int arr(char* x)//实现计算字符串长度的函数
{
if (*x == '\0')//当add数组的某一个元素为'\0'时,就结束递归
{
return 0;
}
else
{
return 1 + arr(x + 1);
//如果当前add数组的元素不为'\0'时,那么就进入递归
//每进入一次递归最后的返回值就+1
}
}
int main()
{
char add[] = "abcdefg";
int ch = arr(add);
printf("%d", ch);
return 0;
}
最后需要注意的是,递归在解决一些问题的时候可能真的很简单明了,但是不是所有的问题都是适合用递归去解决,有时候用循环可能会比用递归更便捷