




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 6 章 函 数 和 模 块 设 计,第 6 章 函数和模块设计,对大千世界的许多描述大都可以在计算机中运用程序设计中的函数问题来解决,C语言程序设计也不例外。 一个功能较大的系统,它一定包含有若干个相对独立的子功能,通过子程序模块来描述这些子功能,再通过对这些子程序的组织和调用,来实现整个程序的功能要求。而这些功能比较独立的子程序模块则称之为函数 。本章用于揭开函数的真面目!,2020/8/10,程序设计基础(C语言)wh,4,6.1 结构化程序设计,6.1.1 结构化程序设计的基本概念 结构化程序设计基本思想: 将一个大的程序按功能分割成一些子模块,再通过对这些子模块的组织和调用,来实现
2、整个程序的功能要求。,2020/8/10,程序设计基础(C语言)wh,5,#include stdio.h void main( ) float a,b,c,v; scanf(”%f,%f,%f”, ,输出体积,组织和调用,计算立方体,示例:编程序计算一立方体的体积,并在屏幕上输出。,2020/8/10,程序设计基础(C语言)wh,6,6.1 结构化程序设计,6.1.1 结构化程序设计的基本概念,结构化程序设计特点: 各模块相对独立、功能单一、结构清晰; 控制了程序设计的复杂性; 提高元件的可靠性 缩短开发周期; 避免程序开发的重复劳动; 易于维护和功能扩充; 开发方法: 自上向下,逐步求精
3、,模块化 ,限制使用goto语句。,2020/8/10,程序设计基础(C语言)wh,7,6.1 结构化程序设计,6.1.2 结构化程序设计的基本特征,1. 程序的三种基本结构,2020/8/10,程序设计基础(C语言)wh,8,2. C语言是模块化程序设计语言,2020/8/10,程序设计基础(C语言)wh,9,3.程序设计采用自顶向下逐步细化过程,2020/8/10,程序设计基础(C语言)wh,10,6.2 函数的定义和调用,函数是C语言程序的一种基本组成部分, C语言程序的功能是通过函数之间的调用来实 现,一个完整的C语言程序可由一个或多个函 数组成。,2020/8/10,程序设计基础(C
4、语言)wh,11,示例:编一个程序,计算一立方体的体积, 并在屏幕上输出立方体的体积。,#include stdio.h void main( ) float a,b,c,v; scanf(”%f,%f,%f”, ,说明:,C是函数式语言,必须有且只 能有一个名为main的主函数, 执行总是从main函数开始, 在main中结束。,一个C语言程序可由一个或 多个函数组成。,C语言中函数与函数之间都是 互相独立的,不能嵌套定义。,除main函数之外,其他函数 是通过调用来执行的。,自定义函数必须先定义后使用,volume函数中的return(v) 语句是返回语句,2020/8/10,程序设计基础
5、(C语言)wh,12,6.2 函数的定义和调用,6.2.1 函 数 的 定 义,一 般 格 式,函数类型 函数名(形参类型说明表) 说明部分 语句部分 ,传统格式,函数类型 函数名(形参表) 形参类型说明 说明部分 语句部分 ,现代格式,2020/8/10,程序设计基础(C语言)wh,13,函数类型 函数名(形参类型说明表) 说明部分 语句部分 ,现代格式,函数返回值类型 缺省 int 型 无返回值 void,合法标识符,可以为空 也可以有多个参数,例 无参函数 void print_message( ) printf(”v=%f”,v); ,2020/8/10,程序设计基础(C语言)wh,1
6、4,6.2 函数的定义和调用,6.2.2 函 数 的 调 用,一.函数调用格式及执行过程,调用形式,函数名(实参列表);,说明: 实参与形参个数相等,类型一致,按顺序一一对应; 实参列表求值顺序,因系统而定(Turbo C 自右向左); 实参的量可以是常量、有值的变量或运算表达式.,2020/8/10,程序设计基础(C语言)wh,15,【例6_3】 实参求值顺序举例。,运行结果: n=0,运行结果: n=1,i(1),+i(2),a(1),b(2),c=0;,i(2),+i(2),a(2),b(2),c=1;,2020/8/10,程序设计基础(C语言)wh,16,函数调用语句的执行过程: 首先
7、计算每个实参表达式的值,并把此值存入所对应 的形参单元中, 执行流程转入函数体,执行函数体中的各语句。 函数体执行完之后,return (c)返回到调用该函数的 函数中的调用处的下一条语,/*计算面积*/ #include stdio.h void main( ) int x=5,y=4,s=0; s=f(x,y); printf(”ns=%dn”,s); f(int a,int b) c=a*b; return(c); ,x=5 y=4,a=5 b=4,c=5*4=20,s=20,运行结果: s=20,2020/8/10,程序设计基础(C语言)wh,17,二. 函 数 的 调 用 方 式,3
8、. 以函数调用中的一个实际参数形式调用 例如 k=hust(hust(m,n),j); printf(”%d”,power(a,b);,2. 以函数表达式的一个运算对象形式调用 例如 k=hust(m,n)*hust(i,j);,1. 以函数调用语句形式调用 例如 hust( );,2020/8/10,程序设计基础(C语言)wh,18,三.对被调用函数的使用说明,在程序中调用另一个函数时,要满足以下三个条件: 被调用函数可以是已存在的用户自定义函数或库函数。, 若是库函数,应用#include命令将有关库函数所需的信息包含到本文件中,#include stdio.h void main( )
9、printf( “*”); , 若是用户自定义的函数,且该函数与调用它的函数(即调用函数)在同一个源 文件中,则在调用函数中应对被调用函数返回值的类型加以说明。,2020/8/10,程序设计基础(C语言)wh,19,#include stdio.h void main( ) float volume(float a,float b,float c) float x,y,z,v; scanf(”%f%f%f”, ,【例6_4】 求长方形体积的程序。,对自定义函数volume说明,调用自定义函数volume,2020/8/10,程序设计基础(C语言)wh,20,6.2 函数的定义和调用,6.2.3
10、 函数的返回值,返回语句形式,return(表达式);,说明: 系统默认的返回值类型为int型 当函数有返回值时,凡是允许表达式出现的地方,都可以调用该函数 当函数没有返回值时,函数的返回值类型可以说明为void型(空类型) 若无return语句,遇 时,自动返回调用函数 函数中可有多个return语句,或,return 表达式;,或,return ;,功能:利用return语句,将计算结果(或不带结果)返回给调用程序,同时,也使程序的执行流程转到调用语句的下一语句去执行。,2020/8/10,程序设计基础(C语言)wh,21,float count(int n) int i; float s
11、; if(n=0); printf(”The%d is invalid”,n); return(0); else s=0; for(i=1;i=n;i+) s+=1/(float)i; return(s); ,【例6_5】编一函数,求112131n的值。,强制转换成实型,2020/8/10,程序设计基础(C语言)wh,22,void spc(int n) int i; for(i=0;in;i+) printf(”%c”, ); return(0); ,【例6_6】 打印n个空格的函数。,void spc(int n) int i; for(i=0;in;i+) printf(”%c”, );
12、 ,返回调用函数,或,2020/8/10,程序设计基础(C语言)wh,23,void line(int n),line(int n) int i; for(i=1;i=n;i+) printf(”%c”,-); return; 调用该函数: printf(”%d”,line(30); ,当无返回值的函数将void省掉时, 函数将返回一个不确定的值。例如:,输出一段虚线的同时,还输出line函数的返回值,它是一个不确定的值。,引起编译错误,2020/8/10,程序设计基础(C语言)wh,24,double power(float x,int n) int i; double pw; pw=l;
13、for(i=1;i=n;i+) pw*=x; return pw; ,【例6_7】编一函数,求x的n次方的值,其中n是整数。,将 x、n 做为 函数参数,结果通过return语句 返回调用程序,2020/8/10,程序设计基础(C语言)wh,25,to_str(int n) char str10; int i; if(n0); while(-i=0) putchar(stri); ,【例6_8】将一个给定的整数转换成相应的字符串后显示出来。,将数值型的数据转换成数值字符的内码,2020/8/10,程序设计基础(C语言)wh,26,6.2 函数的定义和调用,6.2.4 函数参数及函数间的数据传递
14、,形式参数:定义函数时函数名后面括号中的变量名。 实际参数:调用函数时函数名后面括号中的表达式。,例如,形参与实参,2020/8/10,程序设计基础(C语言)wh,27,/*计算面积*/ #include stdio.h void main( ) int x=5,y=4,s=0; s=f(x,y); printf(”ns=%dn”,s); f(int a,int b) c=a*b; return(c); ,实参,形参,2020/8/10,程序设计基础(C语言)wh,28,6.2 函数的定义和调用,6.2.4 函数参数及函数间的数据传递,形式参数:定义函数时函数名后面括号中的变量名。 实际参数:
15、调用函数时函数名后面括号中的表达式。,形参与实参,说明: 实参可以是常量、已赋值的变量或表达式。 实参在次序、类型和个数上应与相应形参表中的形参保持一致。 通常,当需要从调用函数中传值(或传地址)到被调用函数中的形参时应设置实参。,2020/8/10,程序设计基础(C语言)wh,29,6.2 函数的定义和调用,6.2.4 函数参数及函数间的数据传递,值的传递 :调用函数将实参(常数、变量、数组元素或可计算 的表达式)的值传递到被调用函数形参设置的临时变量存储 单元中,被调用函数形参值的改变对调用函数的实参没有 影响。调用结束后,形参存储单元被释放,实参仍保持原 值不变。,传递形参值的两种方法,
16、特点 : 形参与实参占用不同的内存单元. 单向传递,2020/8/10,程序设计基础(C语言)wh,30,#include stdio.h void main( ) int i=25; printf(”The value of i in main( ) before calling sqr(x) is %dn”,i); printf(”Calling sqr(x):sqr(%d)=%dn”,i, sqr(i) ); printf(”The value of i in main( ) after calling sqr(x) is %dn”,i); sqr(int x) x=x*x; retur
17、n(x); ,【例6_9】值的传递程序举例,运行结果: The value of i in main( ) before calling sqr(x) is 25 Calling sqr(x):sqr(25)=625 The value of i in main( ) after calling sqr(x) is 25,结论: 在值的传递调用中,只是实参的复制值被传递, 被调用函数中的操作不会影响实参的值。,2020/8/10,程序设计基础(C语言)wh,31,6.2 函数的定义和调用,6.2.4 函数参数及函数间的数据传递,地址的传递 :调用函数将实参(数组名或指针型变量)的地址 作为参数
18、传递给形参。若实参是数组名,则调用函数将实参 数组的起始地址传递给形参的临时变量单元;若实参是指针 变量或地址表达式,则调用函数将实参指针变量所指向单元 的地址或实参的地址传递给形参的临时变量存储单元。,传递形参值的两种方法,特点 : 形参与实参占用相同的内存单元. 双向传递 实参和形参必须是地址常量或变量,2020/8/10,程序设计基础(C语言)wh,32,void f(int b ) int max,max_i,i; max=b0,max_i=0; for(i=0;i10;i+) if(maxbi) max=bi;max_i=i; max=b0; b0=bmax_i; bmax_i=ma
19、x; return; ,#include stdio.h void main( ) void f(int b ); int a10,i; for(i=0;i10;i+) scanf(”%d”, ,【例6_11】将数组中的最大元素值与第一个元素值交换,运行结果: 0 1 2 3 4 5 6 7 8 9 9 1 2 3 4 5 6 7 8 0,结论: 在地址的传递调用中,数组b与数组a共用同一存储空间。 所以被传递的数据在被调用函数中对存储空间的值做出某种 变动后,必然会影响到使用该空间的调用函数中变量的值。,2020/8/10,程序设计基础(C语言)wh,33,6.2 函数的定义和调用,6.2.
20、4 函数参数及函数间的数据传递,一、非数组名作为函数参数,参数传递的两种形式,当非数组名作为函数参数,在函数调用时,C语言 编译系统根据形参的类型为每个形参分配存储单元,并 将实参的值复制到对应的形参单元之中,形参和实参分 别占用不同的存储单元,且形参值的改变不影响与其对 应的实参,即按“值的传递”方法操作。,2020/8/10,程序设计基础(C语言)wh,34,f(int a,int b) a=a+2; b=b+4; printf(”a=%d,b=%dn”,a,b); return(a); ,#include stdio.h void main( ) int f(int a,int b);
21、int x=1,y=2,z; static int a =0,1,2,3,4; z= f(x,y) ; printf(”z=%d,x=%d,y=%dn”,z,x,y); z= f(a3,a4); printf(”z=%d,a3=%d,a4=%dn” ,z,a3,a4); z= f(x,y+1); printf(”z=%d,x=%d,y=%dn”,z,x,y); ,【例6_12】非数组名作为参数的值的传递程序举例,运行结果:,a=3,b=6,z=3,x=1,y=2,a=5,b=8,z=5,a3=3,a4=4,a=3,b=7,z=3,x=1,y=2,2020/8/10,程序设计基础(C语言)wh,
22、35,6.2 函数的定义和调用,6.2.4 函数参数及函数间的数据传递,二、数组名作为函数参数,参数传递的两种形式,单个数组元素可以作为函数参数,这同非数组名作为 函数参数的情形完全一样,即遵守”值传递”方式。,2020/8/10,程序设计基础(C语言)wh,36,1、数组名作为函数参数的表示方法,当数组名作为函数参数时,需要对其类型进行相应的说明 例如 int test(int array10) . ,若数组说明时不指定数组的长度 ,可用另一个参数来表示数组的长度 例如 int test(int array,int n ) . ,用形参n来表示array数组的实际长度,更灵活,2020/8/
23、10,程序设计基础(C语言)wh,37,int solve( int a ,int n) int sum,i; sum=0; for(i=0;in;i+) if(ai!=0) sum+; return(sum); ,【例6_13】编一函数,用来统计一个一维数组中非0元素的个数,用形参n来表示a数组的实际长度。,2020/8/10,程序设计基础(C语言)wh,38,1、数组名作为函数参数的表示方法,当多维数组名作为函数参数时,除第一维可以不指定长 度外,其余各维都必须指定长度。 例如 check(float a 10,float n) . ,下面的参数说明都是不正确的: 例如 float a ;
24、 或 float a10 ; . ,2020/8/10,程序设计基础(C语言)wh,39,说明:, 用数组名作为函数参数时,应该在调用函数和被调用函数 中分别定义数组。, 实参数组和形参数组类型应一致,否则出错。, 形参数组的大小应大于等于实参数组的大小,否则得不到 实参数组的全部值。, 特别注意的是,数组名作为函数参数时,是将实参数组 的首地址传给形参数组,两数组的对应元素占用同一内 存单元。传递时按数组在内存中排列的顺序进行。,2020/8/10,程序设计基础(C语言)wh,40,2、数组名作为函数参数的传递方式,数组名作为函数参数时,不是采用“值传递”方式, 而是采用“地址传递”方式。
25、这意味着形参数组中某一元素的改变,将直接影响到 与其对应的实参数组中的元素。,2020/8/10,程序设计基础(C语言)wh,41,void sort(int array10) int i,j,k,t; for(i=0;i9;i+) k=i; for(j=i+1;j10;j+) if(arrayjarrayk) k=j; t=arrayk; arrayk=arrayi; arrayi=t; ,#include stdio.h void main( ) int x10,i; void sort(int array10); for(i=0;i10;i+) scanf(”%d,”, ,【例6_14】
26、将一个10个元素的一维数组用函数调用实现选择排序。,9,8,7,6,5,4,3,2,1,0,The sorted array:,0,1,2,3,4,5,6,7,8,9,scanf(”%d,”,2020/8/10,程序设计基础(C语言)wh,42,6.3 嵌套调用和递归调用,C语言中的函数定义是互相独立的,函数和函数之间 没有从属关系,即一个函数内不允许包含另一个函数的定 义。一个函数既可以被其他函数调用,同时,它也可以调 用别的函数,这就是函数的嵌套调用。函数的嵌套调用为 自顶向下、逐步求精及模块化的结构化程序设计技术提供 了最基本的支持。,2020/8/10,程序设计基础(C语言)wh,43
27、,6.3 嵌套调用和递归调用,6.3.1 函数的嵌套调用,嵌套调用,一个函数既可以被其他函数调用,同时,它也 可以调用别的函数,这就是函数的嵌套调用。,嵌套调用执行过程,调用函数a,调用函数b,2020/8/10,程序设计基础(C语言)wh,44,6.3 嵌套调用和递归调用,6.3.2 函数的递归调用,递归调用,在调用一个函数过程中又出现直接或间接地 调用该函数本身,前者称之为直接递归调用,后 者称之为间接递归调用。,2020/8/10,程序设计基础(C语言)wh,45,float func(int n) int m; float f; f=func(m); . ,直接递归调用,间接递归调用,
28、2020/8/10,程序设计基础(C语言)wh,46,long int fact(int n) long int f; if(n=0) f=1; else f=n*fact(n-1); return(f); ,#include stdio.h void main( ) int n; long int result; long int fact(int n); while(1) printf(”Input a number:”); scanf(”%d”, ,【例6_16】 从键盘输入一非负整数n,并求出n!的值。,n!=n*(n-1)!,结果分析: n=4 f(4)= 4*fac(4-1) =3
29、 f(3)= 3*fac(3-1) =2 f(2)= 2*fac(2-1) =1 f(1)= 1*fact(1-1) =0 f(0)= 1,运行情况: Input a number: 4,Result =24,if(n=0) /*递归终止条件*/ f=1;,递归过程的两个阶段: fact(4)是主函数调用的。在一次调用fact函数时 并不是立即得到fact(4)的值,而是一次又一次地 进行递归调用(回推),直到fact(1)时才有确定的值。 之后,再递推出fact(2)、 fact(3)、 fact(4)的值。,2020/8/10,程序设计基础(C语言)wh,47,double xpower(
30、float x,int n) if(n=0) return(1); else return(x*xpower(x,n-1); ,#include stdio.h void main( ) double xpower(float x,int n); float x; int n; double r scanf(”%f%d”, ,【例6_17】编一程序,利用函数的递归调用求x的n次方的值,其中n为正整数。,运行情况: 2,3,Result =8,小结: 任何有意义的递归调用总是由两部分组成: 即递归方式与递归终止条件。,if(n=0) /*递归终止条件*/ return(1);,2020/8/10
31、,程序设计基础(C语言)wh,48,6.4 作用域和存储类型,变量是对程序中数据的存储空间的抽象,变量的属性 数据类型:变量所持有的数据的性质(操作属性) 存储属性 存储器类型:寄存器、静态存储区、动态存储区 生存期:变量在某一时刻存在 静态变量与动态变量 作用域:变量在某区域内有效 局部变量与全局变量,变量的存储类型 auto 自动型 register 寄存器型 static 静态型 extern 外部型,变量定义格式: 存储类型定义符 数据类型 变量名表;,如: int sub; auto int x,y,z; register int n; static float a,b;,2020/
32、8/10,程序设计基础(C语言)wh,49,6.4 作用域和存储类型,6.4.1 局部变量及其存储类型,定义,在 函数 或 复合语句 内部定义的变量称为 局部变量。,说明 主函数main中定义的变量也只在主函数中有效,其它函数不能引用; 不同函数中可以使用相同名字的变量,它们代表不同的对象,占用不同的内存单元,互相独立; 形式参数也是局部变量; 可以在复合语句中定义变量,其作用域只是本复合语句。,2020/8/10,程序设计基础(C语言)wh,50,float hust1(int a) int x, y; ,举 例,局部变量a、x、y的作用范围,float hust2(int b,int c)
33、 char s; ,局部变量b、c、s的作用范围,void main( ) int m, n; ,局部变量m、n的作用范围,2020/8/10,程序设计基础(C语言)wh,51,举 例,#include ”stdio.h” void main( ) int p, q; int x; x=p+q; ,x 的有效范围,p、q的有效范围,2020/8/10,程序设计基础(C语言)wh,52,6.4 作用域和存储类型,6.4.1 局部变量及其存储类型,1.自动存储变量 auto,自动存储变量 在函数或复合语句中定义和说明的变量,通常称为自动变量。自动变量前可以冠以“auto”,若变量前不加任何存储类别
34、说明 ,则按缺省规则都为自动存储类别的变量。,作用域: 自动变量通常是局部变量,它的作用域仅限于定义它的那个函数或复合语句。它的可见性与生存期和作用域相同。,2020/8/10,程序设计基础(C语言)wh,53,【例6_18】 不同函数中的同名变量,#include stdio.h void main( ) int a; a=0; data( ); a=a+100; printf(”main:a=%dn”,a); data( ) int a; a=-199; printf(”data:a=%dn”,a); ,运行结果: data:a=-199 main:a=100,#include stdio
35、.h void main( ) int a; a=1; data( ); a=a+100; printf(”main:a=%dn”,a); data( ) int a; printf(“da=%dn,a); a=-199; printf(”data:a=%dn”,a); ,运行结果: da=1 data:a=199 main:a=101,2020/8/10,程序设计基础(C语言)wh,54,【例6_18】 不同函数中的同名变量,#include stdio.h void main( ) int a; a=10; printf(“ma=%d,%xn,a, ,运行结果: ma=10,ffdc da
36、=404,ffd6 daa=405,ffd6 data:a =199,ffd6 main:a=110,ffdc,2020/8/10,程序设计基础(C语言)wh,55,6.4 作用域和存储类型,6.4.1 局部变量及其存储类型,2. 静态局部变量 static,如果希望在函数调用结束后仍然保留函数中定义的局部变量的值,则可以将该局部变量定义为静态局部变量。 静态局部变量前可以冠以“static ”,例如 static int t,s;,说明: 静态局部变量的作用域在定义它的函数内部,它的值在函 数调用结束后并不消失,但其他函数仍然不能访问它。 静态局部变量赋初值是在编译过程中进行的,且只赋一次
37、初值。而且连续保留上一次函数调用时的结果。 静态局部变量的默认初值数值型为0,字符型为Null,2020/8/10,程序设计基础(C语言)wh,56,【例6_19】编一程序,观察静态局部变量在调用过程中的情况。,#include stdio.h void test( ) static int a=0; printf(”a=%dn”,a); +a; void main( ) int i; for(i=0;i4;i+) test( ); ,运行结果: a=0,a=1,a=2,a=3,2020/8/10,程序设计基础(C语言)wh,57,#include int func(int a,int b)
38、static int m=0, i=0; i+=m+1; m=i+a+b; return(m); main() int k=3,m=2,p; p=func(k,m); printf(“p1=%dn”,p); p=func(k,m); printf(“p2=%dn”,p); ,运行结果: p1=,课堂练习:看程序写结果,*i=i+(m+1)=0+(0+1)=1*,*m=1+3+2=6*,*i=i+(m+1)=1+(6+1)=8*,*m=8+3+2=13*,6,p2=,13,2020/8/10,程序设计基础(C语言)wh,58,6.4 作用域和存储类型,6.4.1 局部变量及其存储类型,3. 寄存
39、器变量 register,为提高程序的运行速度,可将使用十分频繁的局部变量说明为寄存器变量,即在局部变量前冠以register,告知编译系统将其存储在CPU的寄存器中,void test_r(register int n) register char c; . ,说明: 变量的存储类型为寄存器变量时,auto说明符可省,冠以register说明符即可 寄存器变量的使用与机器的硬件特性有关,有一些限制: 如寄存器变量的个数; 它只适用于自动变量和函数的形参; 它的类型只能是char、short int、unsigned int、int和指针型; 不允许对寄存器变量取地址等。 Turbo C中寄存
40、器变量只能用于整型和字符型,且限制最多只允许定义两个 寄存器变量。一旦超过,系统就自动地将其余的作为非寄存器变量来处理。,2020/8/10,程序设计基础(C语言)wh,59,i的作用范围,【例6_20】 输出1到5的阶乘的值。,#include stdio.h void main( ) int fac(int n); int i; for(i=1;i=5;i+) printf(”%d!=%dn”,i,fac(i); int fac(int n) register int i,f=1; for(i=1;i=n;i+) f=f*i; return(f); ,运行结果: 1!=1,2!=2,3!=
41、6,4!=24,i、f的作用范围,5!=120,2020/8/10,程序设计基础(C语言)wh,60,【例6_21】编一程序,输入10名学生的成绩,并求出平均成绩,#include stdio.h float ascore(float a ,int n) register int i; float sum; sum=0; for(i=0;in;i+) sum+=ai; return(sum/n); ,void main( ) float array10; register int i; for(i=0;i10;i+) scanf(”%f”, ,i的作用范围,i的作用范围,2020/8/10,程
42、序设计基础(C语言)wh,61,6.4 作用域和存储类型,6.4.2 全局变量及其存储类型,定义,一个源程序文件可以包含一个或若干个函数。 在函数之外定义的变量称为全局变量或全程变量(又称外部变量)。,全局变量与局部变量的区别: 全局变量在函数之外定义,局部变量在函数之内定义; 局部变量在本函数之内有效,全局变量从定义变量的位置开始到本源文件结束均有效。 编译时全局变量分配在静态存储区,而局部变量则不一定。,2020/8/10,程序设计基础(C语言)wh,62,【例6_22】编一程序,打印九九表,#include stdio.h void row(); int a=1; /*外部变量*/ vo
43、id main( ) int k; for(k=1;k=9;+k,+a) row( ); void row( ) int b; for(b=1;b=a;+b) printf(”%4d”,a*b); printf(”n”); ,2020/8/10,程序设计基础(C语言)wh,63,6.4 作用域和存储类型,6.4.2 全局变量及其存储类型,1. 外部变量 extern,外部变量 没有说明为static的全局变量,其存储类型都是外部的,统称为外部变量。 外部变量说明 extern 数据类型 变量表;,注意: 凡在函数外定义的全局变量,按缺省规则可以不写说明extern, 但在函数体内说明其后所定义
44、的全局变量时,要冠以extern。 若一个文件要引用另一个文件中的全局变量,应该在需要引用该 变量的文件中,用 extern说明该变量为外部的全局变量。,2020/8/10,程序设计基础(C语言)wh,64,【例6_23】编一程序,打印九九表,#include stdio.h void row(); void main( ) int k; for(k=1;k=9;+k,+a) row( ); int a=1; /*定义外部变量*/ void row ( ) int b; for(b=1;b=a;+b) printf(”%4d”,a*b); printf(”n”); ,extern int a;
45、 /*说明外部变量*/,extern只能用来说明变量,而不能用来定义变量。,2020/8/10,程序设计基础(C语言)wh,65,例如 在不同的文件中引用外部变量,文件f1.c的内容: # include “f2.c” int x; /*外部变量定义*/ main() int sum,y; scanf(“%d”, ,2020/8/10,程序设计基础(C语言)wh,66,6.4 作用域和存储类型,6.4.2 全局变量及其存储类型,2. 静态外部变量 static,静态全局变量一定是在本文件中定义的全局变量,其存 储类型说明符是static。 静态全局变量的作用域是其定义点开始到该文件的结束,在本
46、文件外不能访问。 这种全局变量起到一个屏蔽作用。也可以对函数定义成 静态的,来限制函数的作用域。,静态外部变量与外部变量的相同与区别: 两者都是在静态存储区中分配单元; 外部变量不仅在本函数之内使用,还可以用于其他函数,但静态外部变量则不能用于其他函数;,2020/8/10,程序设计基础(C语言)wh,67,例如 下面对静态全局变量的引用是错误的:,file1.c static int a; /*静态外部变量定义*/ main() a=1; printf(”%dn”,f(a); file2.c extern int a; /*静态外部变量引用说明*/ int f(int x) x=a+x; p
47、rintf(”%dn”,x); return(x); ,即使使用了extern说明,也无法使用该变量。,2020/8/10,程序设计基础(C语言)wh,68,6.5 内部函数和外部函数,C语言程序系统由若干个函数组成,这些 函数既可在同一文件中,也可分散在多个不同 的文件中,根据函数能否被其它源文件调用, 可将它们分为内部函数和外部函数。,2020/8/10,程序设计基础(C语言)wh,69,6.5 内部函数和外部函数,6.5.1 内部函数(静态函数 ),如果一个函数只能被本文件中其它函数所 调用,称为内部函数(或静态函数)。 定义时在函数类型前加static: static 类型标识符 函数
48、名,static float hust(int a,int b) ,函数hust的作用范围仅局限于定义本文件,而在其它文件中不能调用此函数。,2020/8/10,程序设计基础(C语言)wh,70,6.5 内部函数和外部函数,6.5.2 外 部 函 数,外部函数 在函数定义的前面冠以extern说明符的函数,称为外部函数。定义外部函数 extern 类型标识符 函数名,说明: 在定义函数时省去了extern说明符时,则隐含为外部函数。 在需要调用外部函数的文件中,应该用extern说明所用的函数 是外部函数。,2020/8/10,程序设计基础(C语言)wh,71,【例6_24】输入一个字符,将已
49、知字符串中的该字符删除,要求用外部函数实现。,/*file1.c*/ #include stdio.h“ void main( ) extern enter_string(char str80); extern delete_string(char str ,char ch); extern print_string(char str ); char c; static char str80; enter_string(str); scanf(”%c”, ,/*file2.c*/ #include “stdio.h“/*输入字符串*/ extern enter_string(char str8
50、0) gets(str);,/*file3.c*/ #include stdio.h“/*删除给定的字符 */ extern delete_string(char str ,char ch) int i,j; for(i=j=0;stri!=0;i+) if(stri!=ch) strj+=stri; strj=0; ,/*file4.c*/ /*打印操作结果 */ extern print_string(char str ) printf(”%s”,str); ,运行结果: abcdefgc,c,abcdefg,2020/8/10,程序设计基础(C语言)wh,72,上机操作过程:,方法一:
51、(1)在file1.c文件开头加入如下内容#include ”file2.c” #include ”file3.c” #include ”file4.c” (2)对file1.c文件进行编译、连接、运行。,方法二: 分别对4个文件进行编译得到四个目标文件 (.obj文件)。 用link功能将四个目标文件连接起来: 在MS C系统上用命令: link file1+ file2+ file3+ file4 执行结果生成一个可执行文件(.exe文件),2020/8/10,程序设计基础(C语言)wh,73,6.6 模块化程序设计,在程序设计时,如果待解决的问题比较简单, 所编制的程序又不大,可将整个程
52、序放在一个模块 中。但对大而复杂的设计任务,不可能由1个人用1 个程序来实现。,2020/8/10,程序设计基础(C语言)wh,74,6.6 模块化程序设计,6.6.1 模块化程序设计方法的指导思想,基本思想:将一个大的程序按功能分割成一些小模块。,开发方法:自顶向下,逐步求精 。,特点: 各模块相对独立、功能单一、结构清晰、接口简单。 控制了程序设计的复杂性。 提高元件的可靠性。 缩短开发周期。 避免程序开发的重复劳动。 易于维护和功能扩充。,2020/8/10,程序设计基础(C语言)wh,75,C语言是模块化程序设计语言,C是函数式语言 必须有且只能有一个名为main的主函数 C程序的执行
53、总是从main函数开始,在main中结束 函数不能嵌套定义,可以嵌套调用,2020/8/10,程序设计基础(C语言)wh,76,程序设计采用自顶向下逐步细化过程,2020/8/10,程序设计基础(C语言)wh,77,6.6 模块化程序设计,6.6.2 模块分解的原则,模块分解用“自顶向下”的方法进行系统设计,即先整体后局部。 复杂系统化大为小,化繁为简。 按功能划分法把模块组成树状结构,层次清楚,提高系统设计 效率(多人并行开发),便于维护。 模块的大小要适中,语句行数不大于100行。 各模块间的接口要简单。 尽可能使每个模块只有一个入口,一个出口。,2020/8/10,程序设计基础(C语言)
54、wh,78,模块的划分和设计可参考如下规则:,(1)如果一个程序段被很多模块所共用,则它应是一个独立的模块。 (2)如果若干个程序段处理的数据是共用的,则这些程序段应放在一个 模块中。 (3)若两个程序段的利用率差别很大,则应分属于两个模块。 (4)一个模块既不能过大,也不能过小。过大则模块的通用性较差,过 小则会造成时间和空间上的浪费。 (5)力求使模块具有通用性,通用性越强的模块利用性越高。 (6)各模块间应在功能上,逻辑上相互独立,尽量截然分开,特别应避 免用转移语句的模块间转来转去。 (7)各模块间的接口应该简单,要尽量减少公共符号的个数,尽量不用 共用数据存储单元,在结构或编排上有联
55、系的数据应放在一个模块 中,以免相互影响,造成查错困难。 (8)每个模块的结构应尽量设计成单入口,单出口的形式。这样的程序 便于调试,阅读和理解且可靠性高。,2020/8/10,程序设计基础(C语言)wh,79,6.7 应 用 举 例,2020/8/10,程序设计基础(C语言)wh,80,【例6_25】编一程序,从键盘为一个1010维整型数组输入数据,并对该数组进行转置操作,即行、列互换。,#include stdio.h void rotate(int a1010) int i,j,temp; for(i=0;i10;i+) for(j=i+1;j10;j+) temp=aij; aij=a
56、ji; aji=temp; ,void main( ) int a1010,i,j; for(i=0;i10;i+) for(j=0;j10;j+) scanf(”d”, ,说明: 由于rotate函数的参数a是数组,因此,它采用的是“地址传递”方式,即 rotate函数中形参a数组的改变,直接影响到在main函数中调用rotate函数 时的实参数组a。,2020/8/10,程序设计基础(C语言)wh,81,分析:题意要求计算字符串长度。可以用字符数组来存储字符串。 主函数main用来输入字符串和输出字符串长度值,函数strlen()用 来计算字符串长度。其递归结束条件是元素值为0,此时,应返
57、回 字符串长度,否则应判断下一个字符。,【例6_26】编写一个计算字符串长度的递归函数。,#include stdio.h int i=0; void main( ) int str_len(char s); char str100; printf(”Input string:n”); gets(str); printf(”Output string:n”); puts(str); i=str_len(str); printf(”The string length=%dn”,i); ,int str_len(char s) if(si=0) return(i); else i+; str_le
58、n(s); ,说明:程序的递归函数中,若不满足条件(si=0)时,一方面长度 I 要加 1,另一方面 将数组中下一个元素的地址作为实参进行递归调用。这是因为 s 是数组的第一个元素的 地址,则 s+1 是第二个元素的地址, s+I 是第 i+1 个元素的地址。,2020/8/10,程序设计基础(C语言)wh,82,【例6_27】变量存储类型及作用域应用举例,/*文件file1.c内容*/ #include stdio.h“ int i=1; next( ) return(i+); void main( ) int i,j; i=reset( ); for(j=1;j=3;j+) printf(”i=%dtj=%dt”,i,j); printf(”next( )=%dt”,next( ); pr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 劳动合同法在企业的实施调查报告(2025年版)
- 2025年股权转让框架协议
- 2025年离婚协议书两个小孩模板
- 【单元重点难点】译林版(三起)英语三年级上册Unit-7-单元复习(知识梳理检测)-(含解析)
- 2025年河北省邢台市单招职业适应性测试题库学生专用
- 2024年运载火箭遥测系统检测设备项目资金需求报告代可行性研究报告
- 第九章 第2节 液体的压强(教学设计)2024-2025学年人教版(2024)物理八年级下册
- 2025年海口市单招职业倾向性测试题库参考答案
- 2025年广东省外语艺术职业学院单招职业适应性测试题库一套
- 《小数除法-谁打电话时间长》(教学设计)-2024-2025学年五年级上册数学北师大版
- 2025年黑龙江交通职业技术学院单招职业技能测试题库必考题
- 2024-2025学年山东省潍坊市高三上学期1月期末英语试题
- 2025-2030年中国青海省旅游行业市场现状调查及发展趋向研判报告
- 人力资源部门2023年度招聘效果分析
- 八年级数学下册 第1章 单元综合测试卷(北师版 2025年春)
- 舞蹈艺术赏析课件
- 2025年春新外研版(三起)英语三年级下册课件 Unit1第1课时Startup
- 2025年安徽碳鑫科技有限公司招聘笔试参考题库含答案解析
- 2025广东珠海高新区科技产业局招聘专员1人历年高频重点提升(共500题)附带答案详解
- 数学-福建省泉州市2024-2025学年高三上学期质量监测(二)试卷和答案(泉州二模)
- 员工行为守则及职业道德规范
评论
0/150
提交评论