首页 > 代码库 > StdC--day5 函数
StdC--day5 函数
HighLight:
1. 函数定义
2. 函数返回值
3. 函数参数
4. 数组做参数传递
5. const 形式参数
6. 递归和汉诺塔
1. 函数定义和声明
---- 定义 返回值的数据类型 函数名 (参数列表)
---- 声明 隐士声明
int fuction();
---->如果返回值不是int,最好使用函数原型声明
---->函数声明时,可以省略参数,省略参数=可以接受任意的参数。void代表不接受参数。
---->函数在隐式声明时,形参的类型如果是short/char/float,会自动提升为 int/int/double。因此,在编程时,尽可能使用函数原型或把被调用函数放上面。
2. 函数返回值
---- 函数返回值必须和return的返回值类型一样
---- 如果函数没有返回值 指定为void
---- c语言中 返回值的类型可以省略 默认为int
3. 函数参数
---- e.g. 用函数交换两个整数的数值
#include "stdafx.h"#include <stdio.h>void swap(int a,int b){ int t =a; a=b; b=t; printf("swaping a=%a,b=%b\n",a,b); }int _tmain(int argc, _TCHAR* argv[]){ int a=1,b=5; printf("before swaping a=%d,b=%d\n", a, b); swap(a,b); printf("after swaping a=%d,b=%d\n", a, b); getchar(); return 0;}
---- 值传递:C语言中实际参数和形式参数之间采用 值传递的方式来传递数据。所以swap函数已经成功交换,但是在main中数值仍旧保留是原样。(在被调函数中 使用的是实际参数的一个拷贝数据)
---- 也就是说在上一个例子中,我们在swap函数中交换了a和b,那只是主函数x,y数据的一个备份,不能够对main函数中的x,y产生影响,就像我们修改了一个复印件,不会对原件造成任何影响。
---- 数组也可以作为函数的参数,采用数组作为函数的参数可以解决这个问题
4. 数组做参数传递
---- 传递的是数组的名字(数组的第一个元素的开始地址)
---- e.g. 用数组的方式传递参数 完成交换
2 #include <stdio.h> 3 4 int swapArr(int a[]) 5 { 6 int s=a[0]; 7 a[0]=a[1]; 8 a[1]=s; 9 printf("$swapArring...$ a[0]=%d,a[1]=%d\n",a[0],a[1]); 10 } 11 12 int swap(int a, int b) 13 { 14 int s=a; 15 a=b; 16 b=s; 17 printf("*swaping...* a=%d,b=%d\n", a,b); 18 } 19 20 int main() 21 { 22 int a=2,b=8; 23 printf("before #swap# a=%d,b=%d\n",a,b); 24 swap(a,b); 25 printf("After #swap# a=%d,b=%d\n",a,b); 26 printf("------------------------------\n"); 27 int arr[2]={2,8}; 28 printf("before #swapArr# arr[0]=%d,arr[1]=%d\n",arr[0],arr[1]); 29 swapArr(arr); 30 printf("After #swapArr# arr[0]=%d,arr[1]=%d\n",arr[0],arr[1]); 31 }
---- 数组作为参数的时候,传递的是数组的首地址,而在内存中,地址是唯一的,无论是在main函数中修改,还是在swap以及其他函数中修改一个地址上的内容,都会对这个地址产生效果。
---- e.g. 用sizeof函数计算数组的大小
#include "stdafx.h"#include <stdio.h>int sizeofarr(int a[]){ return sizeof(a);}int _tmain(int argc, _TCHAR* argv[]){ int a[20]={0}; printf("sizeof a is %d",sizeofarr(a)); getchar(); return 0;}
运行结果 4.
也就是说,在一个函数中测试作为形式参数的数组的长度是 不能实现的,原因:数组传递的时候传递的是地址。
----设计形式参数为数组的函数时候, 应该设计两个参数 一个是数组,另外一个是数组的长度
p14
5. const 形式参数
---- const 只读变量, 只读变量不允许修改
---- 如果形参传递的是地址,又不希望在被调函数更改地址上的内容 这个时候可以使用 const修饰形参。
---- e.g 传递数组参数改为const类型
20 int swapArrConst(const int a[]) 21 { 22 int s=a[0]; 23 a[0]=a[1]; 24 a[1]=s; 25 printf("using const swaping...a[0]=%d,a[1]=%d\n",a[0],a[1]); 26 }编译报错:swapArr.c: In function ‘int swapArrConst(const int*)‘:swapArr.c:23:10: error: assignment of read-only location ‘* a‘swapArr.c:24:7: error: assignment of read-only location ‘*(a + 4u)‘
---- 函数的终止
return 和 exit(0)
exit(0)需要#include <stdlib.h>
6. 递归和汉诺塔
---- 自身调用自身的函数,循环迭代
---->可能造成死循环或者算法复杂化。因此使用递归函数时候必须注意:
1) 必须有退出条件
2) 确保递归后算法简化
---- 计算n的阶乘
1 #include <stdio.h> 2 3 int fact(int n){ 4 5 if(n==1) 6 return 1; 7 return n*fact(n-1); 8 } 9 10 int main() 11 { 12 printf("pls enter one number: \n"); 13 int num=5; 14 scanf("%d",&num); 15 printf("\n %d\n",fact(num)); 16 return 0; 17 }
---- 斐波拉契数列
//数列 1 1 2 3 5 8 13 21 ...要求计算第n项//f(n) = f(n-1)+f(n-2); f(1)=f(2)=1;
1 #include <stdio.h> 2 3 int fee(int n) 4 { 5 if(n<3) 6 return 1; 7 return fee(n-1)+fee(n-2); 8 } 9 10 int fee2(int n) 11 { 12 //f(n-1)=x f(n)=y 13 //y=f(n-1)+f(n)=f(n+1) 14 //x=f(n+1)-f(n-1)=f(n) 15 long long int x=1,y=1,i; 16 for(i=3;i<n;i++) 17 { 18 y=x+y; 19 x=y-x; 20 } 21 return y; 22 } 23 24 int main() 25 { 26 printf("pls input one number"); 27 int input; 28 scanf("%d",&input); 29 printf("the number is %d \n",input); 30 int result =fee(input); 31 printf("result: %d\n",result); 32 return 0; 33 }~
f (n) = f (n - 1) + f (n - 2); // 递归导致算法复杂。
fee2() 使用递推解决
---- 汉诺塔
#include <stdio.h>void han(int n,char a,char b,char c){ if(n<=0) return; han(n-1,a,c,b);//n-1个盘子从a移到b c作中转 printf("%d:%c->%c\n",n,a,c);//第n个盘子a移动到c han(n-1,b,a,c);//n-1个盘子从b移到c a作中转}//1+2+4+8=2^n-1int main(){ han(4,‘A‘,‘B‘,‘C‘); return 0;}
---- 立方根
---- 排列组合
---- 万年历