函数
1.函数是什么?
有输入参数并有返回值
2.函数分为库函数和自定义函数
可以查找所有函数的网站:( (stdio.h) - C++ Referencehttp://www.cplusplus.com/reference/cstdio/
库函数---让c语言更加标准化,
----频繁大量的动作不用自己写,提升效率
常用的函数如下
-
IO函数
-
字符串函数
-
字符操作函数
-
内存操作函数
-
时间/日期函数
-
数学函数
-
其他函数
自定义函数
#include <stdio.h> void 函数名 (形参1,形参2);//函数原型 //函数返回值类型 void 表示无返回值。 //函数名 //函数参数 int main(int argc, char const *argv[]) { 函数名(实参);//调用函数 return 0; } void 函数名 (形参1,形参2)//定义函数 { code;//函数体 //返回值 如果是void return后面不跟任何值加个;就行 return 可以是一个变量的值/常量/可求出值的表达式 }
3.函数参数
实参:真实(自己输入的值,或赋给变量的值)传给函数的值
可以是变量/常量/表达式/ 函数---函数返回的是一个值
这些必须有确定的值,以便把这些值传送给形参
形参:函数名括号中的变量,它只有在函数被调用的过程中才分配内存单元
当函数调用完成后就自动销毁了,所有它只在函数中有效
它是实参的临时拷贝
4.函数调用
传值调用:函数形参和实参分别站不同的内存块,对形参的修改不会影响实参----传一个值
传址调用:把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式---传地址
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量---在函数里面通过地址(是函数外部变量的地址)来控制外部变量
void add(int *p)//定义一个指针,用来接收地址
{
(*p)++;//*p--取p存放的地址中存放的值
//(*p)等于每调用一次函数让num的值每次加1
}
int main()
{
int num =0;
add(&num);//将num的地址传到add函数里
printf("%d",num);//此时输入1
add(&num);
printf("%d",num);//输出2
add(&num);
printf("%d",num);//输出3
return 0;
}
5.函数的嵌套调用和链式访问
嵌套调用
void text1()
{
printf("wulawula\n");
}
void text2()
{
int i;
for(i=0;i<3;i++)
{
text1();
}
}
int main()
{
text2();
return 0;
}
链式访问---把一个函数的值作为另外一个函数的参数
#include<string.h>
int main()
{
int len=strlen("abc");//获得字符串的长度,不带最后一个空字符
printf("%d",len);
printf("%d",strlen("abc"));//这就是链式访问,
//把strlen函数的值3作为printf函数的第二参数的位置上
}
6.函数声明和定义
函数声明:
-
告诉编译器有个函数叫什么,参数是什么,返回类型是什么,
-
函数声明一般在函数的使用之前,先声明在使用
-
函数定义在主函数前面就不用声明在主函数后面就在头文件出声明
函数定义:函数的具体实现,交代函数的功能实现
比如一个大工程分成四个人做,ABCD每人负责一个部分,最后拼起来,这样每人各写各的,最后集中在一起
A程序员
创建一个.h和一个.c的文件,文件名字相同,便于分辨
add.h文件//
int add(int x,int y);//声明文件
add.c文件//函数的实现
int add(int x,int y)
{
return x+y;// 返回x+y的值;
}
B程序员,C程序员,D程序员的做法和A一样
总工程
#include <stdio.h>
#include "add.h"//使用A程序员的函数
int main()
{
int a=20;
int b=10;
int num=add(a,b);//调用add函数
printf("%d",num);
return 0;
}
7.函数递归
-
程序调用自身的----编程技巧称为递归
-
递归做为一种算法在程序设计语言中广泛应用
-
一个过程或者函数在其定义或说明中有直接或间接调用自身的一种方法
-
把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题求解
-
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了代码量
递归的两个必要条件--必须有
-
存在限制条件,当满足这个限制条件的时候,递归便不再继续
-
每次递归调用后越来越接近这个限制条件---可以用if
#include<stdio.h>
void print(unsigned int n,int m);
int main()
{
unsigned int num = 0;
int count= 1;//调用函数次数
scanf("%d", &num);
print(num,count);//打印参数部分数字的每一位
return 0;
}
void print(unsigned int n,int m)
{
printf("这是第%d次调用\n", m);
if (n > 9) {//限制条件
print(n / 10,m+1);
}
printf("%d ", n % 10);
printf("这是第%d层调用\n", m );
//返回第三层时,m此时是3.各层的递归不会互相影响其中的变量与常量的值
//也就是说,第一层m=1,第二层m=2,但此时在都一层的m=1(假如你返回第一层时,输出m是1)
//1.从main函数里调用函数为第一次调用
//假如最初输入n=1234,进入if>9
//2.第二次调用,n/10=1234/10=123,这时把n=123作为参数传过去
//进入if >9
//3.第三次调用,n/10=123/10=12,这时把n=12作为参数传过去
//进入if>9
//4.第四次调用,n/10=12/10=1,这时把n=1作为参数传过去
//进入if,发现!>9
//所以执行printf("%d ", n % 10);输入1
//当递归到不满足if进入下面的语句后
//就会返回上一层递归
//返回递归时,会开始执行递归函数下面那条语句
//返回第三层递归
//此时n是12,然后输出12%10=2;
//再返回第二层,n=123,输出3
//再返回第一层层,n=1234,输出4;
}
栈溢出
创建一个main函数 会在内存的栈区开辟一个空间给main函数
当调用text函数又会在栈区开辟区域给text
在text函数中又遇到text函数,再在栈区里开辟一块空间,
如此递归直到n!<10000,但是内存总会用完,就会出现栈溢出的情况
所以写递归
不能死递归,每次递归要逼近递归条件
递归层次不能太深
//栈溢出的例子
void text(int n)
{
if(n<10000){
text(n+1);
}
}
int main()
{
int a=1;
text(a);
return 0;
}