首页 > 代码库 > 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 * aswapArr.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;}

   ---- 立方根

   ---- 排列组合

   ---- 万年历