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

(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的寄存器中,需要用时直接从寄存器中取出参加运算

最新文章

  1. Javascript写入txt和读取txt文件的方法
  2. Material Design 概念,环境和基本属性
  3. vector algorithm find
  4. 我的ORM之示例项目
  5. oracle表字段为汉字,依据拼音排序
  6. Linux下的段错误(Segmentation fault)
  7. php5.2 连接 SQL Server2008
  8. Git入门详解
  9. sublime3运行lua
  10. Docker系列(二)组件介绍
  11. NPOI2.0
  12. SQL语句之三简单增删改查
  13. 再次深入理解delphi的类
  14. (转)[老老实实学WCF] 第二篇 配置WCF
  15. javascript 学习随笔2
  16. Scrapy 1.4 文档 05 命令行工具
  17. SLAM+语音机器人DIY系列:(八)高阶拓展——2.centos7下部署Django(nginx+uwsgi+django+python3)
  18. Android 使用正则表达式验证身份证号是否符合规则
  19. GridControl 获取某分组的第一个孩子
  20. Yii2框架加入API Modules

热门文章

  1. Day03 知识点
  2. 搭建python开发环境
  3. JavaScript 将数组中具有相同值的对象 取出组成新的数组
  4. linux-centos-pgsql-Ident authentication failed for user “postgres”错误出现解决方法
  5. 输入http://localhost/,apache出现You don&#39;t have permission to access/on this server.的提示,如何解决?
  6. SQL 还原或备份失败数据库变成单个用户模式无法访问
  7. 以多进程读取oss符合条件的数据为例,综合使用多进程间的通信、获取多进程的数据
  8. Linux下判断磁盘是SSD还是HDD的几种方法
  9. jquery mobile - select and input - horizontal - in same line
  10. LeetCode 454.四数相加 II(C++)