目录
函数分为两类:
1、库函数
2、自定义函数
库函数
库函数是C语言标准中约定好,由编译器的厂商提供的
例如strlen函数
其在库里的基本原型为 size_t strlen (const char*str)
C语言标准中规定:
(1)函数的功能——字符串的长度
(2)函数名 strlen
(3)参数 const char*str
(4)返回类型 size_t
函数放入标准库,标准库里的函数叫做库函数
C语言常用的库函数都有:
IO函数
输入输出函数,放在stdio.h的头文件中,如果要使用,则必须包括专门的头文件
字符串操作函数
strlen strcpy等
strcpy函数:字符串拷贝(包括\0)
char * strcpy ( char * destination, const char * source );
字符操作函数
内存操作函数
时间/日期函数
数学函数
pow函数:求次方
其他函数
memset
void * memset ( void * ptr, int value, size_t num );
把ptr指向的前num个字节替换成value
自定义函数
函数的组成
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
get_max函数的设计
无返回值,无参数的函数:
函数的参数:
实际参数(实参):
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数
形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效
函数的调用:
传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
用于只要值,不用修改的情况
传址调用
函数内部可以直接操作函数外部的变量
用于修改来自外部的变量的情况
要用&和*
布尔类型
专门用于表示真假
_Bool 类型的变量只有2种取值,true和false
可以写作bool或者_Bool
使用时要包含头文件#include
练习
判断一个数是不是素数
判断一年是不是闰年
实现一个整形有序数组的二分查找
调用函数的次数
函数的嵌套调用
函数可以嵌套调用,但是不能嵌套定义
函数的链式访问
把一个函数的返回值作为另外一个函数的参数。
换行(\n)也算一个字符
函数的声明
函数在使用之前,要满足先声明后使用
函数的定义
指的是函数的具体实现
未来工程中代码比较多,函数一般放在.h文件中声明,在.c文件中实现
为什么要将代码拆成.c .h
(1)多人协作
(2)代码保护
把代码编译成静态库.lib(乱码)后,交给他人配合头文件使用,不会泄露关键信息
函数递归
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归策略,只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
递归的两个必要条件
(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续。
(2)每次递归调用之后越来越接近这个限制条件
函数之所以能实现调用和递归,都是因为函数在调用的时候会维护一个函数栈帧
函数调用开始,函数栈帧创建,函数调用结束后,栈帧销毁
栈空间有限制,如果一直往下递推但是不回归,就会面临栈溢出,即栈空间放满了(Stack overflow)
编写一个函数不允许创建临时变量,求字符串的长度。
原始做法
创建了临时变量count的做法
使用函数的递归的正确做法
在递归里最好不要使用带有副作用的代码,++
递归与迭代
求n的阶乘。(不考虑溢出)
求第n个斐波那契数。(不考虑溢出)
递归与迭代的选择
在使用 fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。
使用 factorial 函数求10000的阶乘(不考虑结果的正确性),程序会崩溃。
此时可以将递归改写成非递归
如果使用递归很容易想到且没有缺陷,可以使用递归
但如果写出的递归有明显问题,比如栈溢出、效率低下等,就使用迭代