目录
函数分类
函数分为库函数和自定义函数
库函数
C语言中把常用的功能进行了封装,封装成了一个函数,提供大家使用
列如
IO函数(输入/输出函数):scanf printf getchar putchar
字符串操作函数:strlen strcmp
字符操作函数:islower isupper(判断大小写)
内存操作函数:memset memcmp
时间/日期函数:time
数学函数:sqrt pow
其他库函数
c语言并不去直接实现库函数,而是提供了C语言的标准和库函数的约定,库函数的实现一般是由编译器去实现的
在使用这些库函数的时候一定要包含头文件
自定义函数
自定义函数由我们程序员自己来设计,和库函数一样,有函数名,返回值类型和函数参数
例如
写一个函数可以找出两个函数之间的最大值
#include <stdio.h>
int get_max(int x, int y);
int main()
{
int num1 = 90;
int num2 = 20;
int max = get_max(num1, num2);
printf("%d", max);
return 0;
}
int get_max(int x, int y)
{
return (x > y) ? (x) : (y);
}
函数的参数
实际参数
真实传给函数的参数,叫做实参
实参可以是:常量,变量,表达式,函数等
形式参数
形式参数是指函数名后括号中的变量,形式参数只有在被调用的过程中才被实例化(分配内存单元),当函数调用完成后就自动销毁(在调用时自动创建,自动销毁)
函数的调用
传值与传址
例:写一个函数可以交换两个整型变量的内容
函数的实参和形参分别占有不同的内存块,对形参的修改不会影响到实参
形参是实参的一份临时拷贝
传值:传值,实际是把实参的值赋值给行参,相当于copy。那么对行参的修改,不会影响实参的值
传址: 实际是传值的一种特殊方式,传递的是地址,传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参
练习
写一个函数,实现一个整形有序数组的二分查找
(具体二分查找 http://t.csdn.cn/kTFtP)
#include <stdio.h>
int binary(int arr[], int key, int sz);
int main()
{
int arr[100] = { 0 };
for (int i = 0; i < 100; i++)
{
arr[i] = i + 1;
}
int sz = sizeof(arr) / sizeof(arr[0]);
int key = 0;
scanf("%d", &key);
int flag = 0;
flag = binary(arr,key,sz);
if (flag == -1)
{
printf("没有找到");
}
else
{
printf("找到了,下标为%d", flag);
}
return 0;
}
int binary(int arr[], int key,int sz)
{
int left = 0;
int right=sz-1;
int mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] < key)
{
left = mid + 1;
}
else if (arr[mid] > key)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
函数的嵌套调用和链式访问
嵌套调用
函数之间可以根据实际的需求进行组合,也就是互相调用的
嵌套调用
嵌套定义
函数可以嵌套调用,不可以嵌套定义
链式访问
把一个数的返回值作为另一个函数的参数
函数的声明和定义
函数的声明
1.告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但是具体存不存在,函数声明决定不了
2.函数的声明一般出现在函数的使用之前,要满足先声明后使用
3.函数的声明一般放在头文件中
没有声明,主函数调用prt这个函数时没有找到函数
函数定义
函数的定义是指函数的具体实现,交代函数的功能实现
函数递归
什么是递归
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,递归策略只需少量的程序就能描述解题过程中所需要的多次重复计算,大大减少了程序的代码量、
递归的主要思考方式在于:把大事化小
递归的两个必要条件
1.存在限制条件,当满足这个限制条件时,递归便不再继续
2.每次递归调用之后越来越接近这个限制条件
接受一个整型值(无符号),按照顺序打印它的每一位。
列如:
输出:1234,输入1 2 3 4
#include <stdio.h>
void print(int n);
int main()
{
int num = 1234;
print(num);
return 0;
}
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
先递推再回归
递归与迭代
求n的阶乘(不考虑溢出)
#include <stdio.h>
int fac(int n);
int main()
{
int n = 0;
scanf("%d", &n);
int sum = fac(n);
printf("%d", sum);
return 0;
}
int fac(int n)
{
if (n == 1)
{
return 1;
}
else
{
return n * fac(n - 1);
}
}
求第n个斐波那契数列(不考虑溢出)
#include <stdio.h>
int fib(int n);
int main()
{
int n = 0;
scanf("%d", &n);
int x=fib(n);
printf("%d", x);
return 0;
}
int fib(int n)
{
if (n <= 2)
{
return 1;
}
else
{
return fib(n - 1) + fib(n - 2);
}
}
stack overflow(栈溢出)
问题
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者死递归,这样有可能导致一直开辟栈空间,最终导致栈空间耗尽的情况,这种现象我们称为栈溢出
解决方法
将递归改写成非递归
使用static对象代替栈对象