【初学】C语言-函数与模块化程序设计(自存)

引子

为什么要用到函数?什么是模块化程序设计?
:我们通常将相对独立经常使用的功能抽象为函数。
函数编写完成以后可以重复使用,使用时只需要关心程序的功能而不必关心函数功能的具体实现。这样有利于代码重用,可以提高开发效率,也便于分工合作以及修改维护。这就是模块化程序设计。

我们通过例子来理解模块化程序设计,要求用函数调用实现输出以下的结果:

*************
how do you do!
*************
#include<stdio.h>
#include<string.h>

int main(){
    void printstar();        //声明 printstar 函数
    void print_message();    //声明 print_message 函数

    printstar();            //调用 printstar 函数
    print_message();        //调用 print_message 函数
    printstar();            //调用 printstar 函数

    return 0;
}

void printstar(){    //定义 printstar 函数
    printf("**************\n");
}

void print_message(){    //定义 print_message 函数
    printf("how do you do!\n");
}

总结知识点

  • 定义函数:
    两种定义:有参/无参
    基本格式:类型名 函数名(形式参数列表/可空){函数体}
    类型名表示的是返回值的类型;
    例如:指定函数的类型为 void,表示函数无类型即无函数值,也就是说,执行这两个函数不会返回任何值到 main 函数。

    位置:main函数外部

    规范:指定他的名字、函数返回类型、函数实现的功能以及参数的个数和类型

  • 声明函数:

    基本格式: 函数类型 函数名 (参数);

    位置:main函数之前或者main函数内部开头部分

    作用:函数声明的作用是把有关函数的信息(函数名、函数类型、函数参数的个数与类型)通知编译系统以便于在编译系统对程序进行编译时,在进行到 main 函数调用 printstar 和 print_message 时知道他们是函数而不是变量或其他对象。

  • 调用函数:

    基本格式:函数类型 函数名();

  • 库函数
    对于 C 编译系统提供的库函数,是由编译系统事先定义好的,库文件中包含了对各函数的定义。程序设计者不必自己定义,只需要用 #include 指令把有关的头文件包含到本文件中即可。例如在程序中用到 sqrt,fabs,sin 等数学函数,就必须在文件模块开头写上:#include<math.h>。

  • 参数
    在定义函数的时候函数名后面括号中的变量名称为“形式参数”(简称“形参”)
    在调用语句 c=max(a,b); 中,a 和 b 称为“实际参数”(简称“实参”)。
    举个例子:

#include<stdio.h>

int main(){
    int max(int x,int y);    //声明 max 函数
    int a = 10,b = 20;
    int c;
    //调用max函数
    c = max(a,b);                //a, b 为实际参数;调用max函数,传递的是a,b的值给 max 函数。
    printf("%d",c);

    return 0;
}
//定义max函数:
int max(int x,int y){         //int 代表的是返回值是 int 型
    int z;
    z = x>y ? x:y;
    return (z);                //返回 z
}
  • 返回值
    函数可以通过 return 语句将运算得到的 z 的值带回主调函数。应当注意返回值的类型和函数类型一致。如 max 函数为 int 型,返回值是变量 z,也是 int 类型,两者一致;

    函数分类:
    1) 函 数 = { 库 函 数 用 户 自 定 义 函 数 函数=\left\{ \begin{matrix} 库函数 \\ 用户自定义函数 \end{matrix} \right. ={
    2)
    函 数 = { 无 参 函 数 有 参 函 数 函数=\left\{ \begin{matrix} 无参函数\\ 有参函数 \end{matrix} \right. ={
    注:
    无参函数:调用时,主调函数不向被调函数传递数据。无参函数一般用来执行指定的一组操作,比如 printstar 就是输出一行 “*”。无参函数可以带回也可以不带回函数值。
    有参函数:在调用函数时,主调函数通过参数向被调函数传输数据,例如 strlen(测字符串长度的函数) 就是有参函数,主函数传递一个字符串到 strlen 函数,strlen 返回值是这个字符串的长度。

    函数的嵌套调用递归调用
    1.C 语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能定义另一个函数。
    但是,在定义一个函数A的时候,可以调用另一个已经定义的函数B(调用的时候必须在A中先声明函数B)。

    2.在调用一个函数的过程中又出现直接或间接的调用该函数本身,称为函数的递归调用(递归函数的两个要素为递归表达式和递归出口。)
    例如:定义一个阶乘算法:n!
    f ( x ) = { 1 , n = 0 , 1 n ∗ ( n − 1 ) ! , n > 1 f(x)=\left\{ \begin{matrix} 1 , n=0,1\\ n*(n-1)! ,n>1 \end{matrix} \right. f(x)={1,n=0,1n(n1)!,n>1

int fac(int n){
    int f;

    if(n==0||n==1)
        f = 1;
    else
        f = fac(n-1) * n;

    return f;
}

数组与函数
数组元素可以作为一个函数的实参,不能作为形参。

例如:定义一个Max函数:

int max(int x,int y){
    return(x>y?x:y);
}

在主函数中定义一个变量 m,m 的初值为 a[0],每次调用 max 函数后的返回值存放在 m 中。用打擂台算法,将数组元素 a[1] 到 a[cnt] 与 m 比较,最后的到的 m 就是最大值。
打擂台:

 for(i=1,m=a[0],n=0;i<10;i++){
        if(max(m,a[i])>m){          //若 max 函数返回值大于 m
            m = max(m,a[i]);        //max 函数的返回值取代 m
            n = i;                  //把数组元素的序号记下来,放到 n 中
        }
    }

除了可以用数组元素作为函数的参数外,还可以用数组名做函数参数(包括实参和形参)。
应当注意的是:用数组元素作为实参时,向形参变量传递的是数组所对应数组元素的值,而用数组名做函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址

例题:有一个一维数组 score,内放 10 个学生成绩,求平均成绩。
(使用自定义ave函数求平均值)
不完全代码:

float score[10]//在主调函数中声明该数组
aver = average(score);   //注意这里调用函数时,向形参传递的是数组首元素的地址
 
//定义ave函数
float average(float array[10]){
    int i;//数组下标
    float aver,sum = 0;

    for(i=0;i<10;i++)//遍历数组
        sum = sum + array[i];
    aver = sum / 10;

    return(aver);
}

注意:用数组名作为函数参数,应该在主调函数和被调用函数分别定义数组,例如 array 是形参的数组名score 是实参数组名,分别在其所在函数中定义。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值