版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第7章 函数与预处理命令C 语言程序设计第1页2第7章 函数与预处理命令7.1 概述7.2 函数定义与调用7.3 变量作用域与存放方式7.4 编译预处理第2页37.1 概述 程序结构清楚,可读性好。 降低重复编码工作量。 可多人共同编制一个大程序,缩短程序设计周期,提升程序设计和调试效率。使用函数好处C程序源程序文件n函数1函数m 源程序文件1函数1函数n第3页4【例7.1】求一个整数立方。int cube (int x) /* 函数定义 */ return (x * x * x); main( ) int f, a; printf(nEnter an integer number:); sc
2、anf(%d, &a); f = cube (a); printf(%d * %d * %d = %dn, a, a, a, f);程序运行情况以下:Enter an integer number: 2 2 * 2 * 2 = 8函数调用程序执行总是从main函数开始第4页5 一个C源程序能够由一个或多个源程序文件组成。C编译系统在对C源程序进行编译时是以文件为单位进行。 一个C源程序文件能够由一个或多个函数组成。全部函数都是独立。主函数能够调用其它函数,其它函数能够相互调用。 在一个C程序中,有且仅有一个主函数main。C程序执行总是从main函数开始,调用其它函数后最终回到main函数,在
3、main函数中结束整个程序运行。说明第5页6 函数种类从函数定义形式分: 有参函数在主调(用)函数和被调(用)函数之间经过参数进行数据传递, 如: int cube (int x) 无参函数如:getchar( )在调用无参函数时,主调函数不需要将数据传递给无参函数。从使用角度看: 标准函数(库函数)库函数是由系统提供。如:getchar( )、sin(x)等。在程序中能够直接调用它们。附录A列出了C部分库函数。 用户自定义函数如:例7.1中cube函数。第6页7【例7.2】无参函数定义与调用。void welcome ( ) printf(*n); printf( Welcome to Ch
4、ina n); printf(*n);main( ) welcome( ); 程序输出结果以下:* Welcome to China*第7页87.2.1 函数定义函数定义普通形式函数类型 函数名(类型名 形式参数1, ) 说明语句 执行语句比如:求两个数最大值。 int max(int x, int y) int z; z = x y ? x : y; return( z );类型省略时默认为int类型有形式参数,max为有参函数 第8页9int max(x,y)int x,y; int z; z = x y ? x : y; return( z );int max(x,y) int x,y;
5、或int max(int x,y) 或int max(x,y)int x,y,z; z = x y ? x : y; return( z );花括号中也可认为空,这种函数叫空函数 。 例如:null( ) 不能在函数体内定义其他函数,即函数不能嵌套定义。形参也能够这么定义以下定义都是错误 第9页10函数名(实参表列)在C语言中,把函数调用也作为一个表示式。所以凡是表示式能够出现地方都能够出现函数调用。比如: welcome( ); if (iabs (a)max) max=iabs(a); m=max(c,max(a,b);7.2.2 函数调用函数调用普通形式:第10页11int sum( )
6、 int i,t=0; for (i=1; i=100; i+) t+=i; return (t);main( ) int s; s=sum( ); printf(%dn, s);程序输出结果:5050int sum ( int x ) int i,t=0; for (i=1; iy?x:y; return (z); /* 返回z值 */main( ) int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(max is %dn,c);第15页16函数返回值是经过return语句带回到主调函数。功效:终止函数运行,返回主调函数,若有返回值,将返回值带
7、回主调函数。说明: 若函数没有返回值,return语句能够省略。 return语句中表示式类型普通应和函数类型一致,假如不一致,VC系统警告同时自动将表示式类型转换为函数类型。 函数返回值return 语句格式:return (表示式) ; return 表示式 ;return ;第16页17【例7.8】计算并输出圆面积。s(int r) return 3.14*r*r; main( ) int r,area; scanf(%d,&r); printf(%dn,s(r);自动转换为int型 思索:若要得到双精度实型圆面积,程序应怎样修改程序运行情况以下:212?第17页18 7.2.4 对被调
8、函数申明和函数原型变量要先定义后使用,函数也如此。即被调函数定义要出现在主调函数定义之前。如swap函数:允许整型函数(且参数也是整型)定义出现在主调函数之后。如max函数:假如非整型函数在主调函数之后定义,则应在主调函数中或主调函数之前对被调函数进行申明。void swap(int x, int y) main( ) swap(a,b); main( ) c=max(a,b);max(int x, int y) 第18页19对被调用函数说明 假如使用库函数,应在文件开头用#include命令将调用库函数所需信息包含到文件中来。如: #include “stdio.h” stdio.h是开头文
9、件,其中存放了I/O库函数所用到一些宏定义信息。 #include“math.h” 使用数学库函数应用这条命令。假如使用用户自己定义函数,普通应在主调函数中对被调用函数作类型说明。main( ) float add (float x, float y); float a,b,c; scanf(“%f,%f”,&a,&b); c=add(a,b); printf(“sum is %f”,c);float add (float x, float y) float z; z=x+y; return(z);float add (float x, float y);第19页20对被调函数进行申明普通形式
10、 函数类型 函数名(参数类型1 参数名1,);或 函数类型 函数名(参数类型1,参数类型2,);思索:以下哪种情况需要在主调函数中对被调函数申明被调函数定义在前,主调函数定义在后。主调函数定义在前,被调函数定义在后,且被调函数类型不是整型。被调函数定义在后,但被调函数类型是整型。第二种形式省略了参数名,此种形式也称为函数原型。?第20页217.2.5 数组作函数参数1. 一维数组元素作函数参数main( ) int a5,i,m ; for (i=0; i5; i+) scanf(%d,&ai); m=a0; for (i=1; i5; i+) m=min(m,ai); printf(%dn,
11、 m);【例】求5个数中最小值。int min(int x, int y) return (xy?x:y); 用打擂台方法求最小值。m相当于擂主第21页221. 一维数组名作函数参数数组名表示数组在内存中起始地址。 比如:数组a在内存中从地址开始存放,则a值为。是地址值,是指针类型数据(第8中将介绍指针类型),不能把它看成是整型或其它类型数据。实参是数组名,形参也应定义为数组形式,形参数组长度能够省略,但 不能省,不然就不是数组形式了。 【例】用冒泡法将10个整数排序。第22页23void sort(int b ,int n); void printarr(int b ); main( ) i
12、nt a10 = 11,22,63,97,58,80,45, 32,73,36; printf(Before sort:n); printarr(a); sort(a,10); printf(After sort:n); printarr(a);void printarr ( int b10 ) int i; for (i=0; i10; i+) printf(%5d,bi); printf(n);void sort ( int b , int n ) int i,j,t; for (i=1; in; i+) for (j=0; jbj+1) t=bj;bj=bj+1;bj+1=t; 第23页
13、24 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 63 97 58 80 45 32 73 36(a) 排序前a0 a1 a2 a3 a4 a5 a6 a7 a8 a9b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 32 36 45 58 63 73 80 97(b) 排序后图7.3 调用sort函数b形参 b 实际是一个能够存放地址变量a:实参赋给形参首地址: 首地址: 第24页25#include stdio.hmain( ) void scat(char str1 ,char st
14、r2 ); char s150,s250; int i,k; printf(Input s1:); gets(s1); printf(Input s2:); gets(s2); scat(s1,s2); printf(Output s1:%sn,s1);void scat(char str1 ,char str2 ) int i=0,k=0; for ( ; str1i!=0 ; i+; ) ; for ( ; str2k!=0 ; i+, k+) str1i=str2k; str1i=0;scat函数还可简化为:void scat(char str1 ,char str2 ) int i=0
15、,k=0; for ( ; str1i ; i+ ) ; for ( ; str1i+=str2k+ ; ) ;【例】编程序,实现字符串连接。第25页26以二维数组为例。二维数组名作实参时,对应形参也应该定义为一个二维数组形式。对形参数组定义时能够指定每一维大小,也能够省略第一维大小说明。【例】编程序,将矩阵转置。设转置前为a矩阵,转置后为b矩阵,以下所表示: a=1 2 3 4 5 6 7 89 10 11 121 5 92 6 103 7 114 8 12b=思绪:将a00b00,a01 b10,a02b20,a10b01,aijbji,。2. 多维数组作函数参数第26页27void tu
16、rn( ); main( ) int a34=1,2,3,4,5,6,7,8,9,10,11,12; int i,j,b43; turn(a,b); printf(array b:n); for (i=0; i4; i+) for (j=0; j3; j+) printf(%5d,bij); printf(n); /* 矩阵转置函数 */void turn(int arra 4,int arrb 3) int r, c; for (r=0; r3;r+) for (c=0; c0; i-) a+=sub2(i); return a ; sub2(int n) return n+1; 程序输出结
17、果:9 第29页302. 函数递归调用(略)(1)递归基本概念递归调用:一个函数直接或间接地调用了它本身,就称为函数递归调用。递归函数:在函数体内调用该函数本身。int sub(int x) int y,z; if( ) z=sub(y); else return ;比如:直接调用sub函数本身第30页31(2)递归函数执行过程【例7.16】编一递归函数求n!。思绪:以求4阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件:当n=1或n=0时,n!=1。递归公式:n! =1 (n=0, 1)n(n-1)! (n1)第31页32程序以下:float fac
18、t (int n) float f=0; if(n0) printf(n0,error!); else if (n=0 | n=1) f=1; else f=fact(n-1)*n; return (f);main( ) int n; float y; printf(nInput n:); scanf(%d,&n); y=fact(n); printf(%d!=%-10.0fn,n,y);运行情况以下:Input a integer number:44!=24第32页33递归调用过程 回 推main( ) fact(4) fact(3) fact(2) fact(1) y=fact(4); f
19、=4*fact(3); f=3*fact(2); f=2*fact(1); f=1; return 24 return 6 return 2 return 1 递 推 第33页347.3 局部变量和全局变量及其作用域7.3.1 变量作用域1. 局部变量及其作用域变量作用域:变量在程序中能够被使用范围。依据变量作用域能够将变量分为局部变量和全局变量。局部变量(内部变量):在函数内或复合语句内定义变量以及形参。作用域:函数内或复合语句内。【例7.19】分析下面程序运行结果及变量作用域。问题:一个变量在程序每个函数中都能使用吗?第34页35void sub(int a,int b) int c; a
20、=a+b; b=b+a; c=b-a;printf(sub:ta=%d b= %d c= %dn,a,b,c); 局部变量main( ) int a=1,b=1,c=1; printf(main:ta=%d b= %d c= %dn,a,b,c); sub(a,b); printf(main:ta=%d b= %d c= %dn,a,b,c); int a=2,b=2; printf(comp:ta=%d b= %d c= %dn,a,b,c); printf(main:ta=%d b= %d c= %dn,a,b,c); 局部变量局部变量程序输出结果:main: a=1 b= 1 c= 1s
21、ub: a=2 b= 3 c= 1main: a=1 b= 1 c= 1comp: a=2 b= 2 c= 1main: a=1 b= 1 c= 1第35页362. 全局变量及其作用域全局变量(外部变量):在函数外部定义变量。作用域:从定义变量位置开始到根源文件结束。如在其作用域内函数或分程序中定义了同名局部变量,则在局部变量作用域内,同名全局变量暂时不起作用。【例7.20】全局变量和局部变量作用域。第36页37int a = 5;void f(int x, int y) int b,c; b=a+x; c=a-y;printf(%dt%dt%dn,a,b,c); 局部变量main( ) in
22、t b=6,c=7; f(b,c); printf(%dt%dt%dn,a,b,c); int a=9,b=8; printf(%dt%dt%dn,a,b,c); c=10; printf(%dt%dt%dn, a,b,c); printf(%dt%dt%dn,a,b,c); printf(%dt%dt%dn,a,b,c); 局部变量局部变量程序输出结果:5 11 -25 6 79 8 79 8 109 8 105 6 10全局变量第37页387.3.2 变量存放类别及变量生存期1. 变量生存期与变量存放分类变量生存期:变量在内存中占据存放空间时间。思索:1. 何时为变量分配内存单元? 2.
23、将变量分配在内存什么区域? 3. 变量占据内存时间(生存期)?程序代码区静态存放区动态存放区存放分配动态存放变量静态存放变量第38页392. 变量存放类别变量属性数据类型:决定为变量分配内存单元长度;数据存放形式;数范围。存放类别:决定了变量生存期;给它分配在哪个存放区。第39页40变量定义语句普通形式存放类别 数据类型 变量名1, , 变量名n ;auto(自动) register(存放器)static(静态) extern(外部)A. 自动变量(auto类别) 局部变量能够定义为自动变量。main()int x,y; main()auto int x,y; 自动变量等价可省第40页41 内
24、存分配调用函数或执行分程序时在动态存放区为其分配存放单元,函数或分程序执行结束,所占内存空间即刻释放。 变量初值定义变量时若没赋初值,变量初值不确定;假如赋初值则每次函数被调用时执行一次赋值操作。 生存期 在函数或分程序执行期间。 作用域自动变量所在函数内或分程序内。自动变量第41页42B静态变量(static类别)除形参外,局部变量和全局变量都能够定义为静态变量。局部静态变量(或称内部静态变量)全局静态变量(或称外部静态变量)静态变量静态变量static int a; main( ) float x,y; f( ) static int b=1; 全局静态变量局部静态变量自动变量不能省第42
25、页43 内存分配编译时,将其分配在内存静态存放区中,程序运行结束释放该单元。 静态变量初值若定义时未赋初值,在编译时,系统自动赋初值为0;若定义时赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值 。 生存期整个程序执行期间。 作用域局部静态变量作用域是它所在函数或分程序。全局静态变量作用域是从定义处开始到根源文件结束。静态变量第43页44int c;static int a; main( ) float x,y; char s;f( ) static int b=1; 在函数外定义变量若没有用 static说明,则是外部变量。外部变量只能隐式定义为extern类别,不能显式定义。全局
26、静态变量自动变量局部静态变量外部变量第44页45 extern 数据类型 变量名1,变量名n;或 extern 变量名1,变量名n;注意:外部变量申明用关键字extern,而外部变量定义不能用extern,只能隐式定义。定义外部变量时,系统要给变量分配存放空间,而对外部变量申明时,系统不分配存放空间,只是让编译系统知道该变量是一个已经定义过外部变量,与函数申明作用类似。C. 外部变量(extern类别)第45页46【例7.25】在多文件程序中申明外部变量。file1.c文件中程序以下:int i;main( ) void f1( ),f2( ),f3( ); i=1; f1( ); print
27、f(tmain: i=%d,i); f2( ); printf(tmain: i=%d,i); f3( ); printf(tmain: i=%dn,i);void f1( ) i+; printf(nf1: i=%d,i);file2.c文件中程序以下:extern int i; void f2( ) int i=3; printf(nf2: i=%d,i);void f3( ) i=3; printf(nf3: i=%d,i);程序输出结果:f1: i=2 main: i=2f2: i=3 main: i=2f3: i=3 main: i=3申明外部变量定义外部变量第46页47D. 存放器
28、变量(register类别)只有函数内定义变量或形参能够定义为存放器变量。存放器变量值保留在CPU存放器中。受存放器长度限制,存放器变量只能是char、int和指针类型变量。【例7.26】存放器变量使用。main( ) long int sum=0; register int i; for (i=1; i(Y)?(X):(Y)7.4 编译预处理(续)第55页567.4 编译预处理(续)【例7.30】带参数宏定义。#define MAX(x,y) (x)(y)?(x):(y)main( ) printf(%dn,a,b, MAX(a,b); printf(%dn,MAX(a+m,b+n);分两次
29、替换:将宏名MAX(a,b) 替换成字符串 (x)(y)?(x):(y)。用实参a替换形参x,实参b替换形参y。程序中两个printf语句被展开为:printf(%dn, (a)(b)?(a):(b); printf(%dn, (a+m)(b+n)?( a+m):( b+n);第56页577.4 编译预处理(续)【例7.31】分析下面程序运行后输出结果。#define MA(x) x*(x-1)main( ) int a=1,b=2; printf(%dn, MA(1+a+b);分两次替换: MA(1+a+b) 用x*(x-1) 替换。用1+a+b替换x。printf语句被展开为:printf(%dn, 1+a+b*(1+a+b-1);尤
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 桥梁施工现场文明施工方案
- 半固体制剂项目投资计划书
- 公共充电桩布局建设实施方案
- 电网设备状态检修管理规范
- 工程机械配件项目运营管理方案
- 冬季混凝土施工保温专项方案
- 管道定期检测维护管理手册
- 有机硅生产企业重大危险源评估报告
- 厂区动火作业安全管控实施方案
- 充电基础设施项目节能评估报告
- IPC7711C7721C-2017(CN)电子组件的返工修改和维修(完整版)
- 乳制品gmp培训课件
- 智慧水电厂一体化平台建设技术导则
- 数说成长 共育花开-二年级数学家长会【课件】
- 幼儿园如何家长会培训
- 20起典型火灾事故案例合集-2024年消防月专题培训
- Nikon尼康D3100中文说明书
- DB42T2099-2023基于倾斜摄影测量的城市级实景三维地理场景模型生产技术规程
- 机械振动与电磁振荡课件
- 《生涯规划》第三课时 生涯规划之多元智能
- GB/T 20634.3-2008电气用非浸渍致密层压木第3部分:单项材料规范由桦木薄片制成的板材
评论
0/150
提交评论