美文网首页
03-C语言函数

03-C语言函数

作者: 低头看云 | 来源:发表于2018-09-05 09:18 被阅读0次

    函数

    函数的分类

    • 在C语言中可从不同的角度对函数分类

    • 从函数定义的角度看,函数可分为库函数和用户定义函数两种

      • 库函数: 由C语言系统提供,用户无须定义
      • 用户定义函数:由用户按需编写的函数。
    • 从函数执行结果的角度来看, 函数可分为有返回值函数和无返回值函数两种

      • 有返回值函数: 此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。(必须指定返回值类型和使用return关键字返回对应数据)
      • 无返回值函数: 此类函数用于完成某项特定的处理任务,执行完成后不向调用者返回函数值。(返回值类型为void, 不用使用return关键字返回对应数据)
    • 从主调函数和被调函数之间数据传送的角度看,又可分为无参函数和有参函数两种

      • 无参函数: 在函数定义及函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。
      • 有参函数: 在函数定义及函数说明时都有参数,称为形式参数(简称为形参)。在函数调用时也必须给出参数,称为实际参数(简称为实参)
    • 为什么要定义函数?

      • 首先,如果不定义函数:
        • 重复代码冗余代码过多;
        • 需求发生改变时;需要修改很多代码
      • 如果定义函数
      • 将某些代码封装起来,方便以后的使用;
      • 提高代码的复用性;
      • 使代码更加简洁;
      • 便于维护;

    函数的定义

    • 格式:
    // 标注  有参数有返回值函数的定义
    返回值类型 函数名称(形参列表){
        被封装的函数;
        返回值;
    }
    例子:
    
    int main(){
        printf("hello world");
        return 0;
    }
    
    // 获取最大值
    int getMax(int num1, int num2){
        int max = num1 > num2 ? num1 : num2;
        return max;
    }
    
    
    // 无参数无返回值的函数定义:
    void 函数名(){
        函数体;
    }
    
    // 无参有返回值函数定义
    返回值类型 函数名(){
        函数体;
        return 值;
    }
    
    // 有参无返回值函数定义
    void 函数名(参数类型 形式参数1, 参数类型 形式参数2, ...){
        函数体;
    }
    
    
    
    • 初学者如何定义函数
      • 1.确定函数的名称(给函数起一个有意义的名称,让调用者见名知意)
      • 注意点: 函数名称也是标识符的一种,所以也需要遵守标识符的命名规则: 字母,数字,下划线的驼峰命名;
      • 2.确定形参列表(告诉调用者,调用时是否需要传递一些辅助的数据);
        • 注意点: 形参列表的格式 (数据类型 变量名称, 数据类型 变量名称, ...)
        • 数据类型 变量名称 可以有零个或多个;
      • 3.确定函数的功能代码(也就是要封装的代码)
      • 4.确定返回值和返回值的类型
      • return 的作用之一就是将后面的数据返回给函数的调用者;
    #include <stdio.h>
    int getAverage(int num1, int num2){
        int avg = (num1 + num2) / 2;
        return avg;
    }
    int main()
    {
        int a = 10;
        int b = 20;
    //    int res = (a + b) / 2;
        int res = getAverage(a, b);
        printf("average = %i\n", res);
        return 0;
    }
    
    // 注意点: main函数的作用域和getAverage作用域不同
    
    
    image

    函数的参数和返回值

    • 函数的参数:
      • 函数可以有参数,也可以没有参数;
      • 函数的参数可以是零个或多个;
      • 函数可以有返回值;也可以没有返回值;
      • 注意:如果函数没有返回值,那么返回值类型写void就行;
      • 函数的返回值类型可以是所有C语言类型
    • 形式参数:
      • 定义函数时,函数名后面小括号()中定义的变量成为形式参数,简称形参
      • 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元
      • 因此,形参只有在函数内部有效,函数调用结束返回主调函数后则不能再使用该形参变量
    int getSum(int num1, int num2){  // 形式参数
        return num1+num2;
    }
    
    • 实际参数:
      • 调用函数时,传入的值称为实际参数,简称实参;
      • 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参
      • 因此应预先用赋值,输入等办法使实参获得确定值
    int main(){
        int a = 99, b =100;
        int sum = getSum(a, b); // 实际参数
    }
    
    • 返回值的注意点:
      • 如果函数没有编写返回值类型,那么默认就是int类型!
      • 如果函数的返回值类型和实际return返回的类型不同,那么会隐式(自动)转换为返回值类型;
    test1(){
        return 3.14;
    }
    
    // 返回值为3
    //如果函数的返回值类型和实际return返回的类型不同,那么会隐式(自动)转换为返回值类型
    int test2(){
        return 3.14;  // double
    }
    // 返回值3
    
    int main()
    {
        double res = test1();
        printf("res = %lf",res); // 3.000000
        return 0;
    }
    
    
    • 函数的注意点:
      • 1.函数的名称不能相同;
        • 哪怕返回类型不同,函数名称也不能相同
        • 哪怕形参列表不同,函数名臣也不能相同
      • 2.函数不能嵌套定义,哪怕编译器允许的,也不建议这么干;
      • 3.如果是基本类型的数据作为函数的参数 ,那么在函数内修改形参, 不会影响外面实参的值;
      • 4.在函数的内部不能定义和形参同名的变量
      void test(){
          int num = 666; // 这么定义变量会报错
          printf("num = %i\n", num);
      }
      
      • 函数不要嵌套定义

    函数的声明

    • 函数的定义可以写在函数调用之前,也可以写在函数调用之后,但是要进行函数的声明;

    • 标准的写法:函数的声明只需要将函数定义{前面的代码拷贝即可;

    • 函数声明,就是在函数调用之前告诉系统, 该函数叫什么名称, 该函数接收几个参数, 该函数的返回值类型是什么

    • 函数的声明只需将函数定义{前面的代码拷贝即可

    • 声明函数的注意点:

      • 1.函数的声明只要写在调用之前

        • 也就是说,函数的声明,可以写在函数的外面
        • 也可以写在函数里面
      • 2.函数声明的时候,形参可以不用在指定名称

      • 3.如果函数的返回值类型是整型,那么可以不用编写函数声明(但是还是建议写上);

      • 由于函数声明仅仅是为了告诉编译器,我们有一个什么函数,所以函数的声明是可以声明多次,但是函数的的实现只能一次;

      • 总结:

        • 1.以后但凡函数的定义写在函数调用之前,一定要在调用之前编写函数的声明;
        • 2.函数的声明只会告诉系统函数叫什么,接收几个什么类型参数,返回值是什么类型即可;
        • 3.一般情况下我们会将函数的声明写到函数的外面,而不会写到函数的里面;

    main函数分析

    • main函数分析

      • main是函数的名称, 和我们自定义的函数名称一样, 也是一个标识符
      • 只不过main这个名称比较特殊, 程序已启动就会自动调用它
    • return 0;的含义:

      • 告诉系统main函数是否正确的被执行了
      • 如果main函数的执行正常, 那么就返回0
      • 如果main函数执行不正常, 那么就返回一个非0的数
    • 返回值类型:

      • 一个函数return后面写的是什么类型, 函数的返回值类型就必须是什么类型, 所以写int
    • 在企业开发中,我们是可以通过控制台(cmd)在运行程序的时候给main函数传递参数就可以了

    int main(int argc, const char *argv[])
    {
        
        // 代表数组中有一个元素
        // 代表数组中有两个元素
        // 默认情况下, 系统在调用main函数的时候, 会给argv这个数组中存放一个元素
        
        printf("argc = %i\n", argc);
        printf("argv[0] = %s\n", argv[0]);
        printf("argv[1] = %s\n", argv[1]);
        printf("argv[2] = %s\n", argv[2]);
        return 0;
    }
    

    递归函数

    - 递归: 自己搞自己
    - 递归可以实现循环的功能,但是递归的性能比循环差很多
    - return 只能返回给调用者
    
    // do - while 写法:
    int num = -1;
         do{
              // 提醒用户如何输入数据
             printf("请输入一个正整数,以回车结束;\n");
             // 接收用户输入的数据;
             scanf("%i", &num);
         }while( num < 0);
    
         // 输出
         printf("%i",num);
         
         
    // 递归写法
    
    int test(){
        // 定义用户保存的变量
        int num = -1;
        // 提示用户如何输入数据
        printf("请输入一个正整数,以回车结束;\n");
        // 接收用户输入的数据
        scanf("%i", &num);
        if(num < 0 ){
            // 用户输入不合法
            return test();
        }
        return num;
    }
         
    
    image
    • 循环和递归的区别

      • 能用循环实现的功能,用递归都可以实现;
      • 递归常用于"回溯", "树的遍历","图的搜索"等问题
      • 但代码理解难度大,内存消耗大(易导致栈溢出), 所以考虑到代码理解难度和内存消耗问题, 在企业开发中一般能用循环都不会使用递归
    • 设计一个函数用来计算B的n次方

    #include <stdio.h>
    int pow(int b, int n);
    int main()
    {
        /*
         * 编写一个函数实现    B的n次方;
         * B^n
         *
         * b^0 = 1;
         * b^1 = b;
         * b^2 = b*b;
         * b^3 = b*b*b;
         *
         * b^0 = 1;
         * b^1 = b^0 * b;
         * b^2 = b^1 * b;
         *
         * 规律:  B^n = b^(n-1) * b;
         *
        */
    
        // 定义用户输入的变量
        int B = -1, n = -1;
        // 提示用户输入
        printf("请输入两个数,代表B^n;以逗号隔开\n");
        // 接收用户输入
        scanf("%i,%i", &B, &n);
        // 接收结果
        int res = pow(B, n);
        printf("res = %i\n",res);
        return 0;
    }
    
    // 传入格式: B^n
    int pow(int b, int n){
        if(n == 0){
            return 1;
        }else{
            return pow(b, n-1) * b;
        }
    }
    
    
    
    • 用递归法求N的阶乘
    
    #include <stdio.h>
    int jieCheng(int n);
    int main()
    {
        /*
         * 利用递归实现阶乘
         *
         * 3! = 3*2*1;
         * 2! = 2*1;
         * 1! = 1;
         *
         * 规律  n = (n-1)! * n;
         *
        */
    
        // 定义变量  n;
        int n = -1;
        // 提示输入n
        printf("请输入N的阶乘:\n");
        // 接收用户输入的n
        scanf("%i", &n);
        // 保存结果
        int res = jieCheng(n);
        // 输入结果
        printf("%i! = %i", n, res);
        return 0;
    }
    
    int jieCheng(int n){
        if(n==1){
            return 1;
        }else {
            return jieCheng(n-1) *n;
        }
        return n;
    }
    
    
    • 有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。问 第4个人岁数,他说比第3个人大两岁。问第3个人,又说比第2个 人大两岁。问第2个人,说比第1个人大两岁。最后问第1个人, 他说是10岁。请问第5个人多大?
    #include <stdio.h>
    int getAge(int n);
    int main()
    {
        /*
         * 有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。
         * 问 第4个人岁数,他说比第3个人大两岁。
         * 问第3个人,又说比第2个 人大两岁。
         * 问第2个人,说比第1个人大两岁。
         * 最后问第1个人, 他说是10岁。
         * 请问第5个人多大?
         *
         * 第一个人:  10;
         * 第二个人:  10 + 2;
         * 第三个人:  10 + 2 + 2;
         * 第四个人:  10 + 2 + 2 + 2;
         * 第五个人:  10 + 2 + 2 + 2 + 2;
         *
         * 规律:(n -1) + 2;
         *   其中第几个人是n, 10就是n的默认值;
         *
         *
         *
        */
    
    
        // 定义第n个用户输入的变量
        int n = -1;
        // 提示用户输入
        printf("请输入一个整数:\n");
        // 接收输入
        scanf("%i", &n);
        // 定义岁数
        int age = getAge(n);
        // 输出
        printf("age = %i", age);
        return 0;
    }
    
    
    // 递归实现年龄
    int getAge(int n){
        if(n == 1){
            return 10;
        }else{
            return getAge(n-1) + 2;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:03-C语言函数

          本文链接:https://www.haomeiwen.com/subject/dtbowftx.html