美文网首页
2019-02-26 计算机二级C语言程序设计之函数

2019-02-26 计算机二级C语言程序设计之函数

作者: NoelleMu | 来源:发表于2019-02-26 18:00 被阅读0次

    参考资料:
    《全国计算机等级考试二级教程——C语言程序设计》
    《21天学通C语言》

    库函数

    函数是什么

    函数是已命名的、执行专项任务的独立的C代码段,可选择是否调用它的程序返回一个值。

    • 函数是已命名的。每个函数都有独一无二的函数名。在程序的其他部分使用函数名,可以执行该函数中的语句。这也称为调用函数,可以在函数中调用其他函数。
    • 函数是独立的。函数可以独立执行任务,无需程序其他部分干预。
    • 函数可以向调用它的程序返回一个值。程序调用函数时,会执行函数中的语句,如果需要的话,可以把特定信息传递给调用它们的程序。

    调用C语言标准库函数时要求的include命令行

    include命令行必须以#号开头,系统提供的文件以.h作为文件的后缀,文件名用一对双引号" "或一对尖括号<>括起来。

    注意:include命令行不是C语句,因此不能在最后加分号。

    标准库函数的调用

    对库函数的一般调用形式为:

    函数名(参数表)
    

    在C语言中,库函数的调用可以以两种形式出现:

    1. 出现在表达式中。
    2. 作为独立的语句完成某种操作。

    函数的定义和返回值

    函数定义的语法

    C语言函数定义的一般形式如下:

    函数返回值的类型名 函数名 (类型名 形式参数1,类型名 形式参数2……)       //函数的首部,也称函数头
    {
        说明部分        //函数体
        语句部分
    }
    
    • 函数名和形式参数都是由用户命名的标识符。在同一程序中,函数名必须唯一,形式参数名只要在同一函数中唯一即可,可以与其他函数中的变量同名。
    • C语言规定,不能在函数的内部定义函数
    • 若在函数的首部省略了函数返回值的类型名,则默认函数返回值为int类型
    • 除了返回值类型为int类型的函数外,函数必须先定义(或说明)后调用
    • 若函数只是用于完成某些操作,没有函数值返回,则必须把函数定义成void类型。

    函数定义的例子:

    double add (double a, double b)
    {
        double s;
        s = a + b;
        return s;
    }
    

    分析:在此程序中,第一行称为函数的首部,其中add是函数名,是由用户定义的标识符。在它前面的double是类型名,用来说明函数返回值的类型(通常称为函数返回值的类型),函数值的类型可以是整型、实型、字符型、指针和结构类型。这个例子中的add是双精度型。

    函数名后一对圆括号中是形式参数(简称形参)和类型说明表。在每个形参之前都要有类型名,各形参的定义之间用逗号隔开。

    以上add函数首部之后的一对花括号之间的是函数体,在函数体中的语句用来完成函数的功能。这个例子的功能是求a和b的值。

    函数体可以是空的,例如:

    void dummy ()
    {
    }
    

    定义的函数可以没有形参,函数体内也可以没有任何操作,但函数名后的一对圆括号不能省略

    main()也是一个函数。比较add函数和main函数,会发现它们的结构相同。printf()和scanf()等库函数和用户自定义的函数一样,也是有参数和返回值的函数。

    函数的返回值

    函数的返回值通过return语句返回,return语句的形式如下:

    return 表达式;     或       return (表达式);
    

    也就是说,return语句中的表达式的值就是所求的函数值,此表达式的值的类型必须与函数首部所说明的类型一致。若不一致,则转换为函数值的类型。

    当程序执行到return语句时,程序的流程就返回到调用该函数的地方(通常称为退出调用函数),并带回函数值。在同一个函数内,可以在多处出现return语句,但只有第一个被执行的return语句有效,也就是说return语句只可能执行一次

    return语句中也可能不含表达式,这时必须定义函数为void类型,它的作用只是使流程返回到调用函数,并没有确定的函数值。

    函数体内也可以没有return语句,这时也必须定义函数为void类型,程序的流程就一直执行到函数末尾的“}”,然后返回调用函数,也没有确定的函数值带回。

    这个程序中使用了多条return语句,并返回不同的值:

    #include <stdio.h>
    char last_init;
    int room;
    
    int room_assign(char last_init);
    
    int main (void)
    {
        puts("Enter the first initial of your last name: ");
        scanf("%c", &last_init);
        
        room = room_assign(last_init);
        
        printf("\nYou need to report to room %d.", room);
        
        return 0;
    }
    
    int room_assign(char li)
    {
        //该if语句测试首字母是在A~M之间还是在N~Z之间
        //如果在A~M之间,则分配在1045房间,其余的分配在1055房间
        //||用于检查首字母的大小写
        
        if ((li >= 'a' && li <= 'm') || (li >= 'A' && li <= 'M'))
            return 1045;
        else
            return 1055;
    }
    

    输出1:

    Enter the first initial of your last name:

    d

    You need to report to room 1045.

    输出2:

    Enter the first initial of your last name:

    R

    You need to report to room 1055.

    函数的调用

    函数的两种调用方式

    函数的一般调用形式为:

    函数名 (实际参数名)
    

    实际参数(简称实参)的个数多于一个时,各实参之间用逗号隔开。

    实参的个数必须与所调用函数中的形参相同,类型一一匹配。

    若函数无实参,调用形式为:

    函数名 ()
    

    函数名后的圆括号不可少。

    一般情况下,可用两种方式调用函数:

    1. 当所调用的函数用于求出某个值时,函数的调用可作为表达式出现在允许表达式出现的任何地方。例如对于前面举例的add函数,可以用以下语句求出3.0和4.0的值,然后赋给y(也可以出现在if语句中作为进行判断的表达式):

      y = add (3.0, 4.0);
      
    2. C语言中的函数可以仅进行某些操作而不返回函数值,这时函数的调用可作为一条独立的语句,如:

      dummy();
      

    第一种方法仅适用于有返回值的函数。由于可以对这些函数求值(得到返回值),因此只要是可以使用C表达式的地方都可以使用这些函数。

    例如,下面这条语句中,half_of()是printf()函数的实参:

    printf("Half of %d is %d.", x, half_of(x));
    

    下面这个例子在一个表达式中使用了多个函数:

    y = half_of(x) + half_of(z);
    

    函数调用时的语法要求

    函数调用时有以下语法要求:

    1. 调用函数时,函数名必须与所调用的函数名完全一致
    2. 实参的个数必须与形参的个数一致,且实参可以是表达式。如果类型不匹配,按照赋值兼容的规则进行转换。
    3. C语言规定,函数必须先定义后调用。如果想在main函数中调用前面提到的add函数,在源程序中应把add函数放在main函数的前面。如果被调用的函数返回值为intchar类型,则被调用函数的定义也可以放在调用的位置之后。
    4. C程序中,函数可以自己直接或间接调用自己,称为递归调用

    函数的递归调用

    递归指的是在一个函数中直接或间接地调用自己。如果一个函数调用另一个函数,而后者又调用前者,将发生间接递归。C语言允许递归函数。

    例如,递归可用于计算数的阶乘,计算方法如下:

    x! = x * (x - 1) * (x - 2) * (x - 3) * …… * 2 * 1
    

    还可以这样写:

    x! = x * (x - 1)!
    

    以下这个例子使用递归计算阶乘(注:程序中使用的是unsigned整型,因此输入的值最大为8,9的阶乘超过了unsigned的取值范围):

    //函数的递归示例
    //计算数的阶乘
    
    #include <stdio.h>
    unsigned int f, x;
    unsigned int factorial(unsigned int a);
    
    int main (void)
    {
        puts("Enter an integer value between 1 and 8: ");
        scanf("%d", &x);
        
        if (x > 8 || x < 1)
        {
            puts("Only values from 1 to 8 are acceptable!");
        }
        else
        {
            f = factorial(x);
            printf("%u factorial equals %u\n", x, f);
        }
        return 0;
    }
    
    unsigned int factorial (unsigned int a)
    {
        if (a == 1)
            return 1;
        else
        {
            a *= factorial(a - 1);
            return a;
        }
    }
    

    输出:

    Enter an integer value between 1 and 8:

    6

    6 factorial equals 720

    函数的说明

    函数说明的形式

    对于返回值不是int类型的函数,若把定义放在调用之后,应该在调用之前对函数进行说明(或称为函数原型说明、函数原型),函数说明的一般形式如下:

    类型名 函数名 (参数类型1,参数类型2,……)
    类型名 函数名 (参数类型1 参数名1, 参数类型2 参数名2,……)
    

    例如:

    double add (double, double)
    double add (double p, double q)
    

    注意,第二种类型的参数名完全是虚设的,可以是任意的用户标识符。

    函数说明语句中的类型名必须与函数返回值的类型一致。

    函数说明可以是一条独立的语句,如:

    double add (double, double);
    

    也可以与普通变量一起出现在同一个类型定义语句中,如:

    double x, y, add (double, double);
    

    函数说明的位置

    当在所说明函数的外部、被调用之前说明函数时,在对函数进行说明的语句后面所有位置上都可以对该函数进行调用。

    函数说明也可以放在调用函数内的说明部分,如在main函数内部进行说明,则只能在main函数内部才能识别该函数。

    调用函数和被调用函数之间的数据传递

    C语言中,调用函数和被调用函数之间可以通过三种方式进行传递:

    1. 实参和形参之间进行数据传递。
    2. 通过return语句把函数值返回调用函数。
    3. 通过全局变量。

    在C语言中,数据只能从实参单向传递给形参,称为“按值”传递。也就是说,当简单变量作为实参时,用户不可能在函数中改变对应实参的值。在调用函数时,形参值的变化不会影响对应的实参。

    例如,以下程序师徒通过调用swap函数,把主函数中变量x和y中的数据进行交换。

    #include <stdio.h>
    void swap (int, int);   //函数说明语句
    int main (void)
    {
        int x = 10, y = 20;
        printf("(1) x = %d, y = %d\n", x, y);
        swap (x, y);
        printf("(4) x = %d, y = %d\n", x, y);
        return 0;
    }
    void swap (int a, int b)
    {
        int t;
        printf("(2) a = %d, b = %d\n", a, b);
        t = a;
        a = b;
        b = t;
        printf("(3) a = %d, b = %d\n", a, b);
    }
    

    输出:

    (1) x = 10, y = 20

    (2) a = 10, b = 20

    (3) a = 20, b = 10

    (4) x = 10, y = 20

    由于数据只能从实参单向传递给形参,形参数据变化不会影响对应实参,所以在本程序中,不能通过调用swap函数来交换主函数中的x和y的值。

    函数的位置

    就现在而言,应该把函数放在main()所在的源文件中,并位于main()的后面。

    可以把用户自定义函数放在一个独立的源代码文件中,与main分离。在大型程序中或者要在多个程序中使用同一组函数时,经常会这样做。

    内联函数

    在C语言中可以创建一种特殊类型的函数——内联函数。内联函数通常都很短小。编译器会将函数代码拷贝进主函数里执行内联函数。待执行的代码段将会被放入主函数中,故称之为内联

    使用inline关键字可以将函数设置为内联。例如,下面的代码段声明了一个内联函数toInches():

    inline int toInches (int Feet)
    {
        return (Feet * 12);
    }
    

    程序举例

    例1

    编写函数isprime(int a),用来判断自变量a是否为素数。若是素数,函数返回整数1,否则返回0。

    #include <stdio.h>
    int isprime (int);      //isprime函数的说明语句
    int main (void)
    {
        int x;
        printf("Enter a integer number:");
        scanf("%d", &x);        //从键盘输入一个整数
        if (isprime (x))
            printf("%d is prime\n", x);     //当返回值为1时,输出“是素数”
        else
            printf("%d is not prime", x);       //当返回值为0时,输出“不是素数”
    }
    int isprime (int a)     //定义isprime函数
    {
        int i;
        for (i = 2; i <= a/2; i++)
            if (a % i == 0)     //a一旦能被某个数整除,即不是素数,返回0
                return 0;
        return 1;       //a不能被2到a/2之间任何一个数整除,返回1
    }
    

    例2

    编写函数myupper(ch),把ch中的小写字母转换成大写字母作为函数值返回,其他字符不变。主函数中不断输入字符,用字符@结束输入,同时不断输出结果。

    按要求myupper函数的返回值应该是char类型,程序如下:

    #include <stdio.h>
    #include <ctype.h>
    char myupper (char ch)
    {
        if (ch >= 'a' && ch <= 'z')
            ch = ch - 32;
            return ch;
    }
    int main (void)
    {
        char c;
        while ((c = getchar()) != '@')
        {
            c = myupper (c);
            putchar(c);
        }
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:2019-02-26 计算机二级C语言程序设计之函数

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