函数、递归和递推

1.数组可以作为形式参数使用。

例子:

 

运行结果:

 

 数组做形式参数的时候真正的形式参数不是数组,而是一个可以当作数组使用的变量。

数组形式参数里包含的存储区都不是被调用函数提供的。

 声明数组形式参数的时候可以省略,其中包含的存储区个数。

例子:在外部函数调用数组时可以省略数组的存储区个数。

 运行结果:

 数组形式参数需要配合一个整数类型的形式参数用来表示数组形式参数里包含的存储区个数。 

例子:

数组形式参数可以让被调用函数使用其他函数提供的存储区。 

这种参数叫输入输出参数。

练习:

#include<stdio.h>
int print(int array[],int size){
    for(int i=0;i<size;i++){
        array[i]=0-array[i];
    }
}

int main(){
    int array[]={1,2,3,4,5};
    print(array,5);
    for(int i=0;i<5;i++){
        printf("%d ",array[i]);
    }
    return 0;
}

输出结果:

 

 练习:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int print(int array[],int size){    
    for(int i=0;i<size;i++){
       array[i]=rand()%36+1;
    }
}

int main(){
    srand(time(0));
    int array[7]={0};
    print(array,7);
    for(int i=0;i<7;i++){
        printf("%d ",array[i]);
    }
    return 0;
}

输出结果:

 

C语言里函数参数的个数可以不固定。 

这种参数叫做变长参数。

变长参数不能在编写函数的时候命名,在被调用函数里需要使用特殊的方法才能获得这些参数的内容。

例子:

 上图程序中,这个猜测结果ret叫函数的隐式声明。

函数隐式声明里参数的类型只能是int类型或double类型 

 如果函数的真实格式和隐式声明不一致,编译就会报错。

例子:

运行结果:程序报错

函数大括号前面的部分可以单独作为语句使用,这种语句叫做函数声明语句。

函数声明语句里可以省略形式参数的名称。 

把函数声明语句写在文件开头叫做函数的显式声明。

显示声明可以避免隐式声明。

输出结果:

 

 除了主函数以外的所有函数都应该进行显示声明。

2. exit标准函数可以立即结束程序的执行。

 为了使用这个标准函数需要包含stblib.h头文件

这个函数需要一个整数类型的参数,这个参数的作用和主函数返回值的作用一样。

例子:

 输出结果:return;函数退出的是当前函数,exit(0);函数是退出整个程序。

 3.C语言里函数可以调用自己。

这种函数叫做递归函数。

例子:

输出结果:输出无数个1

 

 如果一个问题可以分解成几个小问题,至少其中一个小问题和原来的问题本质上一样(只是稍微简单一点儿)这种问题就适合采用递归函数解决。

递归函数编写步骤:

(1)编写语句解决分解后的每个小问题。(假设递归函数已经编写完成可以直接使用)

(2)在递归函数开头编写分支处理不可分解的情况(这个分支必须保证函数可以结束)

例子:

 运行结果:

 练习:

#include<stdio.h>
int add(int num){
    if(num==1){
        return 1;
    }
    return add(num-1)+num;

}
int main(){
    int num=0;
    printf("请输入一个数字:");
    scanf("%d",&num);
    printf("求和结果为:%d\n",add(num));

    return 0;
}

运行结果:

用递归函数解决问题的思路叫递归。

用循环解决同样问题的思路叫递推。

 检验递归函数的时候首先用最简单的参数测试,然后逐渐把参数变

 练习:

 

#include<stdio.h>
int func(int num1,int num2){
    //取余函数%
    //当A>B时,A%B的余数正常
    //当A<B时,A%B=A
    if(!(num2%num1)){
        return num1;
    }
   return func(num2%num1,num1);

}
int main(){
    int num1=0,num2=0;
    printf("请输入两个数字:");
    scanf("%d%d",&num1,&num2);
    printf("最大公约数是%d\n", func(num1,num2));
    return 0;
}

 输出结果:

 注意://取余函数%
           //当A>B时,A%B的余数正常
           //当A<B时,A%B=A

练习:

#include<stdio.h>
int func(int num){
      if(num<=1)
      {
          return 1;
      }
        return func(num-2)+func(num-1);
}
int main(){
    int num=0;
    printf("请输入数字:");
    scanf("%d",&num);
    printf("%d\n", func(num));
    return 0;
}

运行结果:

 4.能够使用某个变量的所有语句叫做这个变量的作用域。

 声明在函数里面的变量叫做局部变量它的作用域包含函数里面的所有语句。

例子:

运行结果:编译出错。

声明在所有函数外边的变量叫全局变量,它的作用域包含程序里面的所有语句。

例子:

 输出结果:在主函数main和函数func里都可以调用val变量

 没有初始化的全局变量自动被初始化为0

全局变量和局部变量可以重名。

变量名优先代表局部变量。

例子:

 输出结果:

如果全局变量和局部变量都能解决问题就应该优先考虑使用局部变量。

 存储区的使用不受作用域的限制(可以跨函数使用存储区)。

存储区的使用受生命周期的限制。

生命周期是一段时间,在生命周期开始的时候计算机给程序分配存储区,在生命周期结束的时候计算机把分配给程序的存储区收回。

全局变量的生命周期是整个程序的执行时间。

局部变量的生命周期是函数某一次执行的时间范围。

当函数开始的时候,计算机为局部变量分配存储区,在函数结束的时候计算机把局部变量的存储区收回。

所以如果函数多次执行,每次执行的时候局部变量对应的存储区都可能不同。

例子:

运行结果:第一次在main函数里调用func函数输出num是一个随机数,第二次通过func1函数重新调用func函数,还是随机数,说明当一个函数结束时计算机会立即释放它的存储区。重新找到一块新的随机的存储区,所以函数多次执行时,存储区可能会不同。

 

 静态变量的生命周期和作用域跟普通变量不一样。

5.声明静态变量的时候应该使用static关键字。

不论全局变量还是局部变量都可以声明成静态的。

静态局部变量的生命周期是整个程序的执行时间。

例子:

运行结果: 

没有初始化的静态变量会自动被初始化为0 

静态局部变量的存储区随时可以使用。

静态局部变量的作用域和普通局部变量的作用域是一样的。

例子:

 运行结果:第二次运行func函数时,static函数没有受到初始化影响变成10,而是1000

 注意:静态变量的初始化只在程序开始的时候执行一次。

静态全局变量的生命周期还是整个程序的执行时间,但是它的作用域只包含声明它的那个文件里的所有语句(不可以跨文件使用静态全局变量)

变量的作用域分为三种:局部变量、静态全局变量、全局变量。

变量的生命周期分为两种:普通局部变量、其它变量。

练习:优化后的斐波那契数列:

第一种:

#include<stdio.h>
int func(int num){
    static array[50]={0};
      if(num<=1)
      {
          return 1;
      }
      if(!array[num -2]){
          array[num-2] = func(num-2);
      }
      if(!array[num-1]){
          array[num-1] = func(num-1);
      }
      return array[num-2 ]+array[num-1];
}
int main(){
    int num=0;
    printf("请输入数字:");
    scanf("%d",&num);
    printf("%d\n", func(num));
    return 0;
}

 第二种:

#include<stdio.h>
int array[50]={0};
int func(int num){
      if(num<=1)
      {
          return 1;
      }
      if(!array[num -2]){
          array[num-2] = func(num-2);
      }
      if(!array[num-1]){
          array[num-1] = func(num-1);
      }
      return array[num-2 ]+array[num-1];
}
int main(){
    int num=0;
    printf("请输入数字:");
    scanf("%d",&num);
    printf("%d\n", func(num));
    return 0;
}

第三种:

#include<stdio.h>
int func(int num,int array[],int size){

      if(num<=1)
      {
          return 1;
      }
      if(!array[num -2]){
          array[num-2] = func(num-2,array,size);
      }
      if(!array[num-1]){
          array[num-1] = func(num-1,array,size);
      }
      return array[num-2 ]+array[num-1];
}
int main(){
    int num=0;
    int array[50]={0};
    int size=50;
    printf("请输入数字:");
    scanf("%d",&num);
    printf("%d\n", func(num,array,size));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44954230/article/details/127284280