第七章 用函数实现模块化程序设计

(1)为什么要用函数?

@function既是函数也是功能。函数就是用来完成一定功能的的(函数就是功能),函数名就是给这个功能起一个名字,一个C程序可由一个主函数和若干个其他函数构成。

所有的函数都是平行的,即在函数定义时是分别进行,是互相独立。

例题://输出以下结果,用过调用函数实现
/*
***********
How are you!
***********
*/ #include<stdio.h>
int main()
{
void print_star(); //声明void print_star()函数
void print_message(); //声明void print_message函数
print_star(); //调用print_star函数
print_message(); //调用print_message函数
print_star(); //用print_star函数
return 0;
}
void print_star() //定义void print_star函数,这里后面不能有";"符号
{
printf("****************\n");
}
void print_message() //定义void print_message函数
{
printf("How are you!\n"); //输出一行文字信息
}

(2)怎样定义函数

@在程序中若用到数学函数【如:sqrt、fabs、sin cos等】必须在文本开头写上(#include<math.h>)

函数的定义包括以下几个内容
1.指定函数的名字,以便以后按名调用。
2.指定函数类型,即函数值返回类型。
3.指定函数的名字和类型,在调用时向他们传递数据。
4.指定函数应当完成什么操作,也就是函数应该做什么,就是函数的功能。

定义函数的方法:

1.定义无参函数:
一般形式为:
类型名 函数名() 类型名 函数名(void)
{ {
函数体 或 函数体 //包括声明部分和语句部分
} }
函数名后面括号内的void表示“空”即函数没有参数 2.定义有参函数:
一般形式为: 例如:定义max函数
类型名 函数名(形式参数表列) int max(int x,int y);
{ { int z;
函数体 z=x>y?x:y;
return (z);
} } 3.定义空函数(先占用一个位置,后面在编写好的程序放上去)
一般形式为:
类型名 函数名()
{}
例如: void dummy()
{} 【merge():合并 ; matproduct():矩阵相乘 ; concatenate():字符串连接; shell(): 希尔排序】

(3)调用函数

1.一般形式为:
函数名(实参表列)//若是无参函数,则实参表列可以没有,但是括号不能省
例如: print_star(); //调用无参函数
c=max(a,b)//调用有参函数 2. 3种函数调用方式
函数调用语句 、函数表达式、函数参数 3.函数调用时的数据传递
形式参数和实际参数、实参和形参间的数据传递。 4.函数的调用过程
5函数的返回值
它是通过return语句获得
函数值的类型
再定义函数时指定的函数类型一般应该和return语句中的表达式类型一致
**(如果函数值的类型和return语句中表达式的值不一样,以函数类型为准)

(4)对被调用函数的声明和函数原型:

*函数的首行(即函数的首部)成为函数的原型,使用函数原型作声明是C语言的一个重要特点。

*函数的定义是指对函数功能的确立,包括函数名,函数值类型、形参及其类型以及函数体等,他是一个完整的、独立的函数单位。

函数声明有两种:
1.函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2.....);
2.函数类型 函数名(参数类型1,参数类型2,.....);

(5)函数的嵌套使用:

@C语言的函数定义是相互平行的、独立的,也就是说,在定义函数时,一个函数不能再定义另一个函数就是不能嵌套定义,但可以嵌套使用。

例题1://输入4个整数,找出其中最大的数。用函数嵌套调用来处理。
//方法一:
#include<stdio.h>
int main()
{
int max(int r,int x,int y,int z);
int a,b,c,d,e;
printf("请输入4个整数:");
scanf("%d,%d,%d,%d",&a,&b,&c,&d);
e=max(a,b,c,d);
printf("最大的数为:%d\n",e);
return 0;
}
int max(int r,int x,int y,int z)
{
int m,n,l;
m=r>x?r:x;
n=m>y?m:y;
l=n>z?n:z;
return (l);
} //方法二:
/*
#include<stdio.h>
int main()
{
int max4(int a,int b,int c,int d);//对max4函数的声明
int a;
int b;
int c;
int d;
int max; printf("请输入4个整数:");
scanf("%d,%d,%d,%d",&a,&b,&c,&d); max=max4(a,b,c,d); //调用max4函数,得到4个数中的最大者
printf("最大的数为:%d\n",max);
return 0;
} int max4(int a,int b,int c,int d) //定义max4函数
{
int max2(int a,int b); //对max2函数的声明
int m;
m=max2(a,b); //调用max2函数,得到a和b两个数中的大者,放在m中
m=max2(m,c); //调用max2函数,得到a,b,c三个数中的大者
m=max2(m,d);
return (m);
}
int max2(int a,int b)
{
if(a>=b)
return a;
else
return b;
}
*/

(6)函数的递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。运用递归调用必须有一个递归结束条件

例如1:直接调用本函数举例
int f(int x)
{
int y,z;
z=f(y);//在执行f函数的过程中又要调用f函数
return (2*z);
}

例题2:/*有五个学生坐在一起,
问第五个学生多少岁,他说比第四个学生大两岁。
问第四个学生岁数,他说比第三个大两岁。
问第三个学生,又说比第二个大两岁。
问第二个学生,他说比第一个大两岁。
最后问第一个学生,他说他十岁。
请问第五个学生多少岁?
*/ //递归过程
/*
int age(int n)
{
int c;
if(n==1)
c=10;
else
c=age(n-1)+2;
return(c);
}
*/ #include <stdio.h>
int main()
{
int age(int n);
printf("NO.5,age:%d\n",age(5)); //输出
return 0;
} int age(int n) //定义递归函数
{
int c;
if(n==1) //n=1时,年龄为10
c=10;
else
c=age(n-1)+2; //n!=1时,年龄是前一个学生的年龄加2
return (c);
}
//递归调用4次,
例题3://利用递归算法求n!

#include<stdio.h>
int main()
{
int fac(int n); //fac 函数声明
int n;
int y;
printf("input integer number:"); //输入要阶乘的数
scanf("%d",&n);
y=fac(n);
printf("%d!=%d\n",n,y);
return 0;
}
int fac(int n) //定义fac函数
{
int f;
if(n<0) //n不能小于0
printf("n<0,data error!");
else if(n==0||n==1) //n=0或者1时, (n!)=1
f=1;
else
f=fac(n-1)*n;
return (f);
}

(7)数组作为函数参数

调用有参函数,需要提供实参。可以是常量、变量或着表达式。数组元素也可以作为函数实参。

【数据传递方向是从实参到形参,单向传递。】

1.数组元素作为函数实参,不能作为形参。
例题1://输入 10个数,要求输出其中值最大的元素和该数是第几个数。 #include<stdio.h>
int main()
{
int max(int x,int y);
int a[10];
int m;
int n;
int i;
printf("enter 10 integer numbers:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
printf("\n");
for(i=1,m=a[0],n=0;i<10;i++)
{
if(max(m,a[i])>m)
{
m=max(m,a[i]);
n=i;
}
}
printf("The largest number is %d\n it is the %dth number.\n",m,n+1);
}
int max(int x,int y)
{
return (x>y?x:y);
} 2.数组名作函数参数
【用数组元素做实参时,向形参变量传递是数组元素的值,而用数组名作函数实参时,向形参传递的是数组首元素的地址】
例题2://有一个一维数组score,内放10个学生成绩,求平均成绩 #include<stdio.h>
int main()
{
float average(float array[10]); //函数声明
float score[10];
float aver;
int i;
printf("enter 10 scores:\n");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
printf("\n");
aver=average(score); //调用average函数
printf("average score is %5.2f\n",aver);
return 0;
}
float average(float array[10]) //定义average函数
{
int i;
float aver,sum=array[0];
for(i=1;i<10;i++)
sum=sum+array[i]; //累加学生成绩
aver=sum/10;
return(aver);
} 例题3://有两个班级,分别有35名和30名学生,调用一个average函数,分别求这两个班级的学生的平均成绩。
//为了简化,分别设着两个班的人数为5和10 #include<stdio.h>
int main()
{
float average(float array[],int n);
float score1[5]={98.5,97,91,60,55};
float score2[10]={67,88,99,69,77,89,76,54,60,99};
printf("The average of class A is %6.2f\n",average(score1,5));
printf("The average of class B is %6.2f\n",average(score2,10));//用数组名score1和5做实参
return 0;
} float average(float array[],int n)
{
int i;
float aver,sum=array[0];
for(i=1;i<n;i++)
sum=sum+array[i];
aver=sum/n;
return(aver);
} 3.多维数组名做函数参数
在被调用函数中对形参数组定义时可以制定每一维大小,也可以省略第一维的大小说明
例题://有一个3×4的矩阵,求所有元素中的最大值 #include<stdio.h>
int main()
{
int max_value(int array[][4]); //函数的声明
int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}}; //对数组元素赋初值
printf("Max value is %d\n",max_value(a));// max_value(a)为函数调用
return 0;
}
int max_value(int array[][4]) //函数定义
{
int i;
int j;
int max;
max=array[0][0];
for(i=0;i<3;i++)
for(j=0;j<4;j++)
if(array[i][j]>max)
max=array[i][j];
return (max);
}

(8)局部变量和全局变量

从变量的作用域来(从空间)看可分为全局变量和局部变量。

局部变量:在复合语句内定义的,复和语句不能在外面用的就是局部变量。形式参数也是局部变量。
全局变量:在函数之外定义的外部变量是全局变量。

(9)变量的存储方式和生存期

变量的存储方式分为两类:

1.动态存储方式:是在程序运行期间需要进行动态的分配存储空间的方式【形式参数、自动变量、现场保护和返回地址】
2.静态存储方式:在程序运行期间有系统分配固定的存储空间的方式。【全局变量全部放在这里】 3.存储空间又分为三类:程序区、静态存储区和动态存储区【存放数据】。

*变量的存在时间称之为生存期。

*【每一个C语言都包含的属性有:数据的类型、数据存储类别。】

1.存储类别指的是数据在内存中存储的方式(如静态存储方式和动态存储方式)
2.c的存储类别分为四种:自动的auto 、静态的static、寄存器的 register、外部的 extern
局部变量的存储类别(auto static)
1.在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时会自动释放这些存储空间,这就是自动变量。auto可以隐藏不写;它存储在动态存储区中
2.局部变量的值在函数调用结束后不消失而继续保留原值,及其占用的存储单元不释放,就是静态存储变量。
3.将局部变量的值存储在CPU的寄存器中,需要用时直接从寄存器中取出参加运算

2017.11.13 在C语言中是否能用函数实现模块化程序设计的更多相关文章

  1. 2017/11/13 Leetcode 日记

    2017/11/13 Leetcode 日记 463. Island Perimeter You are given a map in form of a two-dimensional intege ...

  2. VR/AR软件—Mirra测试(截至2017/11/13),使AR/VR创作更加便捷

    Mirra(截至2017/11/13)https://www.mirra.co/ 1.主要特点: 目前仅支持VR,不支持AR 在浏览器(仅支持chrome,firefox)上进行创作,但目前不能直接在 ...

  3. C语言中可变参数的函数(三个点,“...”)

    C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...

  4. C++基础 (8) 第八天 数组指针 模板指针 C语言中的多态 模板函数

    1昨日回顾 2 多态的练习-圆的图形 3多态的练习-程序员薪资 4员工管理案例-抽象类和技术员工的实现 employee.h: employee.cpp: technician.h: technici ...

  5. c语言中不允许在函数外部给全局变量赋值

    今天,在写条件编译的时候,出现了在函数外部给全局变量赋值的情况,gcc报错,那么c语言为什么不允许在函数外部给变量赋值呢?为什么声明变量的时候可以对变量进行赋值? 出错代码: /* 2 * ===== ...

  6. C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .

    我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...

  7. C语言中生产随机数 rand()函数

    参考资料:C语言中产生随机数 一:如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX定义在stdl ...

  8. C语言中变量名及函数名的命名规则与驼峰命名法

    一.C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 1. 只能以字母或下划线开始:2. 不能以数字开始:3. 一般小写:4. 关键字不允许用(eg:int float=2//error  ...

  9. javascript语言中的一等公民-函数

    简介 在很多传统语言(C/C++/Java/C#等)中,函数都是作为一个二等公民存在,你只能用语言的关键字声明一个函数然后调用它,如果需要把函数作为参数传给另一个函数,或是赋值给一个本地变量,又或是作 ...

随机推荐

  1. 练习五十六:for循环

    某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换 方法一: def o ...

  2. 使用xUnit为.net core程序进行单元测试

      第1部分: http://www.cnblogs.com/cgzl/p/8283610.html 第2部分: http://www.cnblogs.com/cgzl/p/8287588.html ...

  3. NET CORE Learning

    ASP.NET Core 基础教程https://www.cnblogs.com/lonelyxmas/tag/ASP.NET%20Core%20%E5%9F%BA%E7%A1%80%E6%95%99 ...

  4. Linux关于用户信息的一些命令

    1.用户增加删除[root@VM_0_13_centos ~]# useradd better407 #添加 better407 用户 [root@VM_0_13_centos ~]# passwd ...

  5. linux开机启动服务学习chkconfig命令

    选项: --add:增加所指定的系统服务,让chkconfig指令得以管理它,并同时在系统启动的叙述文件内增加相关数据: --del:删除所指定的系统服务,不再由chkconfig指令管理,并同时在系 ...

  6. python_案例综合:教材记录管理

    class Book(): def __init__(self,ISBN,Ftile,Author,Publisher): self.ISBN = ISBN self.Ftile = Ftile se ...

  7. git知识点总结

    集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器.集中式版本控制系统最大的 ...

  8. 详解HBase架构原理

    一.什么是HBase           HBase是一个高可靠.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价的PC Server上搭建大规模结构化存储集群.         H ...

  9. intellijidea课程 intellijidea神器使用技巧1-5 idea界面介绍

    菜单栏介绍: file:文件操作edit:文本操作view:视图操作navigate:跳转code:源码文件analyze:项目依赖关系分析refactor:代码重构快捷操作,如:抽取函数build: ...

  10. UITableView分隔线

    问题1: 在ios中使用UITableView时,当行数较少是,可能一屏幕能显示完全所有行,这时候会出现下面的问题,显示多余的分隔线 图如下: 解决方案: //解决方案1 //添加如下代码 -(CGF ...