1 / 38

第 5 章 函数

第 5 章 函数. 输入 2 个正整数 m 和 n, 计算 m! + n!. #include &lt;stdio.h&gt; void main( ) { int I,m,n; double fm,fn; scanf(&quot;%d%d&quot;, &amp;m, &amp;n); fm=1; for(i=1;i&lt;=m;i=i+1) fm=fm*i; fn=1; for(i=1;i&lt;=n;i=i+1) fn=fn*i; printf(&quot;%f<br>&quot;,fm+fn); }. 求 m! 、 n! 同做一过程. m!. f=1;

sari
Download Presentation

第 5 章 函数

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第5章 函数 输入2个正整数m和n,计算 m!+n! #include <stdio.h> void main( ) { int I,m,n; double fm,fn; scanf("%d%d", &m, &n); fm=1; for(i=1;i<=m;i=i+1) fm=fm*i; fn=1; for(i=1;i<=n;i=i+1) fn=fn*i; printf("%f\n",fm+fn); } 求m!、n! 同做一过程 m! f=1; for(i=1;i<=k;i=i+1) f=f*i; n! 用函数做 当k=m; m!=fact(m) 当k=n; n!=fact(n)

  2. 5.1.1 程序解析 计算m!+n!,用函数求解 #include <stdio.h> double fact(int n);/*函数声明*/ void main( ) { int m,n;scanf("%d%d",&m,&n); printf("%f\n",fact(m)+fact(n)); } double fact(int n) /* 定义求 n! 的函数*/ {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result;/* 把结果回送主函数 */ } 主函数 其它函数 C程序由一个主函数或一个主函数与若干其它函数构成

  3. 5.1.2 函数定义 函数:完成一个特定工作的独立程序模块 函数分为:库函数,由C语言系统提供。如:scanf()、printf() 自定义函数,用户自己编写。如:求阶乘函数fact() 1. 函数定义格式 ⑴返回函数值的函数定义 函数首部 格式型标识符 函数名(形式参数表) { 说明语句 执行语句 return 表达式; } 函数体 其中 函数名自定义,按标识符规定命名 形式参数表定义该函数计算依赖的参数和参数类型 类型标识符int、float、double 、char函数返回值的类型 说明语句用于说明语句里用到各数据变量的类型 执行部分各种计算语句 return 表达式;计算函数返回值

  4. 例 编写求n!的函数 函数名 形式参数表 函数首部 double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; } 函数类型 函数体 说明语句 执行语句 函数返回值

  5. ⑵不返回函数值的函数定义 格式void 函数名(形式参数表) { 说明语句 执行语句 return; /* 可省略 */ } 函数首部 函数体 函数返回类型 其中 void空类型,表示函数无返回值 void pyramid(int n) { int i,j; for(i=1;i<=n;i++) {for(j=1;j<=n-i;j++) printf(" "); for(j=1;j<=i;j++) printf("%d ",i); putchar('\n'); } } 例5-2输出数字金字塔 #include <stdio.h> void main( ) { void pyramid(int n); pyramid(5); }

  6. ⑶类型标识符缺省 函数返回值为整型 #include <stdio.h> main( ) { printf("%d\n", fact(5)); } fact(int n) {int i,result=1; for (i=1;i<=n;i++) result=result*i; return result; } 格式 函数名(形式参数表) { 说明语句 执行语句 return 表达式; } 注:源程序文件 .c方式适合。 源程序文件 .cpp方式不适合。

  7. 主函数的几种不同表示 void main() {.... } main() {.... } int main() {.... return 0; }

  8. 2. 函数参数表 定义函数的自变量,函数计算的已知数据 例 编写求n!的函数。 已知 n 计算函数n! double fact(int n) n是函数的参数,称形式参数或简称形参 函数参数表定义方式 ⑴方式1类型标识符 函数名(形式参数表) { 函数体 } 形式参数表格式: 类型1 参数1 ,类型2 参数2,…,类型n 参数n ⑵方式2类型标识符 函数名(形式参数名表) 形式参数类型说明 { 函数体 } 形式参数名表:参数1,参数2,…, 参数n 形式参数类型说明:类型1 参数1,参数2,…, 参数n;类型2 …;

  9. 例 对浮点数x和整数n,编写求xn 的函数。 形式参数名表 形式参数表 double expon(x,n) float x;int n; {double y;int i; y=1; for(i=0;i<n;i++) y=y*x; return y; } double expon(float x,int n) {double y;int i; y=1; for(i=0;i<n;i++) y=y*x; return y; } 形参类型说明 注:源程序文件 .c两种形参定义方式均可。 源程序文件 .cpp只适合第一种方式。 两种定义方式书写不要混淆。 如第一种方式定义: int x,int y,float z 不能写成 int x,y,float z

  10. 3. 函数返回值 函数返回值 通常函数经过计算得到一个函数值 如 fact(3) 得到 6 6是函数返回值 函数返回值需要使用return语句实现 格式return(表达式); 或 return 表达式; 操作 一执行return,先计算表达式,然后中断函数返回函数调用处 表达式值作为函数返回值 double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result;/* 把结果回送主函数 */ }

  11. 注在函数体内return语句个数不限 例5-3定义函数even(n),当n为偶数时返回1,否则返回0 int even(int n) {if(n%2==0) return 1; else return 0; } 当return(表达式)中表达式的值与函数类型不一致,强行转换成函数类型 return只能返回一个数值, 如 return x,y; 只能返回y int fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; } 当函数体内无return语句,函数体执 行完毕返回随机值(void函数除外)

  12. 5.1.3 函数的调用 例5-2 #include <stdio.h> void main( ) { void pyramid(int n); pyramid(5); } void pyramid(int n) { int i,j; for(i=1;i<=n;i++) {for(j=1;j<=n-i;j++) printf(" "); for(j=1;j<=i;j++) printf("%d ",i); putchar('\n'); } } 函数调用:使用函数 1. 函数调用的方法 ⑴函数语句 格式 函数名(实参表列); 一般用于函数无返回值

  13. ⑵作为表达式中的一个元素 格式 函数名(实参表列) 例 计算12! void main() {int i, n; double s; scanf("%d",&n); s=fact(n); printf("s=%f\n",s); } double fact(int n) {int i;double result=1; for (i=1;i<=n;i++) result=result*i; return result; }

  14. 2. 函数参数的传递 参数传递:形参与实参结合 形式参数指函数定义时形式参数表中的参数 实际参数指调用函数时在参数表位置上出现的参数 形参 double expon(float x,int n) {double y;int i; y=1; for(i=0;i<n;i++) y=y*x; return y; } 例 void main() {int a;double t; scanf("%lf,%d",&t,&a); t=expon(t,a); printf("%f\n",t); } 实参 虚实结合 形参与实参的个数、位置、类型一致 个数 形参的个数与实参的个数相同 位置 形参实参依次按排列位置相结合 类型数据类型和参数形式相对应

  15. 类型 一致 数据类型相对应 形参实参 整型 整型 实型 实型 字符 字符 但字符与整型互通 参数形式 形参 实参 变量 常量、变量、表达式 数组 数组、指针 指针 指针、数组 如 double expon(float x,int n) expon(3.5,a+3) 上面讲的形参与实参结合是语法要求,其数据是怎么结合的?

  16. 当形参是变量,虚实结合是单向值传递,即实参赋值于形参当形参是变量,虚实结合是单向值传递,即实参赋值于形参 如函数定义 double expon(float x,int n) 函数调用expon(t,a) 则 t=>x a=>n 计算expon(x,n)后 t,a值不变 例 编写交换两个变量值的函数swap() void main() {int a=1,b=2; swap(a,b); printf("a=%d,b=%d\n",&a,&b); } void swap(int x,int y) {int t; t=x;x=y;y=t; } 运行结果: a=1,b=2 不能交换 形参、实参可用指针实现双向值传递 void main() {int a=1,b=2; swap(&a,&b); printf("a=%d,b=%d\n",&a,&b); } void swap(int *x,int *y) {int t; t=*x;*x=*y;*y=t; } 运行结果: a=2,b=1 交换

  17. 3. 函数执行过程 (1)分配函数的内存单元 (2)虚实结合 (3)执行函数体 (4)函数结束或遇到return返回函数调用处 (5)收回分配函数的内存单元 double expon(float x,int n) {double y;int i; y=1; for(i=0;i<n;i++) y=y*x; return y; } 例 void main() {int a;double t; scanf("%lf,%d",&t,&a); t=expon(t,a); printf("%f\n",t); }

  18. 4. 被调用函数的声明 ⑴使用库函数需要头文件中说明 格式 #include <库文件名.h> 或 "库文件名.h" 如 #include "stdio.h" #include "math.h" ⑵使用自定义函数需要在调用函数的模块中声明被调用函数 格式 类型标识符 被调用函数名(形参说明表); 或 类型标识符 被调用函数名(); 注:源程序文件 .c两种形参定义方式均可。 源程序文件 .cpp只适合第一种方式。

  19. 函数调用说明 函数调用说明 例 #include <stdio.h> void main( ) {double fact(); printf("%f\n",fact(12)/(fact(5)+fact(7))); } double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; } #include <stdio.h> void main( ) {double fact(int n); printf("%f\n",fact(12)/(fact(5)+fact(7))); } double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; }

  20. 允许缺省被调用函数说明,满足下述条件之一 定义的被调用函数出现在调用语句的模块之前 #include <stdio.h> double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; } void main( ) { printf("%f\n",fact(12)/(fact(5)+fact(7))); } fact函数 主函数 调用函数

  21. 被调用的函数类型是int类型说明 #include <stdio.h> main( ) { printf("%d\n", fact(5)); } int fact(int n) {int i, result; result=1; for (i=1;i<=n;i++) result=result*i; return result; } 调用函数 注 仅源程序文件 .c可以。

  22. 在源程序文件的开始说明被调用函数,即在函数的外部说明在源程序文件的开始说明被调用函数,即在函数的外部说明 #include <stdio.h> double fact(int n); void main( ) { printf("%f\n",fact(12)/(fact(5)+fact(7))); } double fact(int n) {int i; double result=1; for (i=1;i<=n;i++) result=result*i; return result; } 函数的外部说明 调用函数 主函数 fact函数

  23. 函数的结构 形式参数表 函数返回值 函数的类型 函数的调用 函数参数的虚实结合 函数执行过程 函数被调用的说明

  24. 函数参数的虚实结合 函数定义 例 对浮点数x和整数n,编写求xn 的函数。 #include <stdio.h> void main() {double expon(float x,int n); int n;float x;double s; scanf("%f,%d",&x,&n); s=expon(x,n); printf("%lf\n",s); } 函数被调用的说明 函数执行过程 (1)分配函数的内存单元 float y,int m; double z;int i; (2)虚实结合 x->y,n->m (3)执行函数体 (4)函数返回return z; 返回函数调用处 (5)收回分配函数的内存单元 float y,int m; double z;int i; 函数的调用 函数的类型 形式参数表 double expon(float y,int m) {double z;int i; z=1; for(i=0,;i<m;i++) z=z*y; return z; } 函数返回值

  25. 5.2 使用函数编写程序 #include <stdio.h> #include <math.h> void main( ) { printf("pi=%f\n",pi); } 求 例5-4按 要求定义和调用函数funpi(double e) 实现。e为计算精度 double funpi(double e); double e,pi; scanf("%lf",&e); pi=funpi(e); #include <stdio.h> #include <math.h> void main( ) { int i,flag; double item,pi; pi=0;flag=1;i=1;item=1; while(fabs(item)>=1e-5) {pi=pi+item; i=i+1;flag=-flag; item=flag*1.0/(2*i-1); } pi=pi*4; printf("pi=%f\n",pi); } double funpi(double e) {int i,flag; double item,pi; pi=0;flag=1;i=1;item=1; while(fabs(item)>=e) {pi=pi+item; i=i+1;flag=-flag; item=flag*1.0/(2*i-1); } pi=pi*4; return pi; }

  26. n= i=2,n,1 1 m%i==0 0 i 0 i≥n+1 1 返回0 返回1 例5-5求100之内的全部素数,1不是素数,2是素数。要求定义和调用函数prime(m)判断m是否为素数,当m为素数返回1,否则返回0 #include "stdio.h" #include "math.h" int prime(int m) { } int i,n; if(m==1) return 0; n=sqrt(m); for(i=2;i<=n;i++) if(m%i==0) break; if(i>=n+1) return 1; else return 0; if(m%i==0) return 0; return 1; void main( ) {int m; for(m=1;m<=100;m++) if(prime(m)) printf("%d ",m); }

  27. 5.3 变量与函数 本节讨论变量的作用域以及与函数的关系 5.3.1局部变量和全局变量 1.局部变量 局部变量函数内部定义的变量,在本函数范围内有效 如程序 float f1(a) int a; {int b,c; …... } char f2(x,y) int x,y; {int i,j; …... } void main() {int m,n; ……. } a,b,c 有效域 m,n 有效域 x,y,i,j 有效域

  28. 注(1)在主函数中定义的变量仅在主函数内有效 (2)函数的形参是局部变量 (3)复合语句中定义的变量作用域只在复合语句内部 例5-6 void main() {int a; a=1; {int b=2; b=a+b; a=a+b; } printf("%d ",a); } b有效域 (4)不同函数中可以定义相同名字的变量,但代表的是不同对象 分配不同的存储单元

  29. 2.全局变量 全局变量在函数外部定义的变量,其有效域为从定义变量的位置起到 本源程序文件结束。 int p=1,q=5; float f1(a) int a; {int b,c;... } char c1,c2; char f2(x,y) int x,y; {int i,j; } main() {int m,n; … } 如源程序文件 全局变量 p,q 有效域 c1,c2 有效域

  30. 注(1)当全局变量与局部变量同名时,在局部变量的有效域内全局注(1)当全局变量与局部变量同名时,在局部变量的有效域内全局 变量不起作用。 例 int a=1,b=5; int max(int a,int b) {int c; c=a>b?a:b; return(c); } main() {int a=8; printf("%d\n",max(a,b)); } 全局变量 局部变量 a,b 有效域 全局变量 a,b有效域 减去局部变量同名的 有效域 局部变量 局部变量 a 有效域 输出 8 (2)全局变量的缺省值(初值)为0

  31. 注(3)利用全局变量进行函数之间数据传递 例 王婆卖瓜:要求每卖一次瓜要记下个数与重量,以统计所卖出瓜的总个数与总重量。另外需要说明的是,王婆允许退瓜。 void main() {char c;float wt;int num; while(1) {switch(c=getchar()) {case 'b':scanf("%d",&num); scanf("%f",&wt); back(num,wt);break; case 's':scanf("%d",&num); scanf("%f",&wt); sale(num,wt);break; case 'q':exit(0);} c=getchar(); printf("%d ", all_number); printf("%f\n", all_weight);}} #include <stdio.h> float all_weight; int all_number; void sale(int number,float weight) {all_number+=number; all_weight+=weight; } void back(int number,float weight) {all_number-=number; all_weight-=weight; } 全局变量 总重量、总个数 利用全局变量传递

  32. 全局变量进行函数之间数据传递运算速度快,但一般不采用,原因是全局变量进行函数之间数据传递运算速度快,但一般不采用,原因是 (1)函数通用性不好,移植困难 (2)程序可读性差 (3)调试程序不方便 当函数有多个返回值可使用数组或指针 void sale(int number,float weight,int *all_number,float *all_weight) {*all_number+=number; *all_weight+=weight; } void back(int number,float weight, int *all_number,float *all_weight) {*all_number-=number; *all_weight-=weight; }

  33. 5.3.2动态存储变量和静态存储变量 变量从作用域的角度来分,分为局部变量和全局变量 从生存时间角度来分,分为静态存储变量和动态存储变量 静态存储程序运行期间分配固定存储空间的方式 动态存储程序运行期间根据需要进行动态分配存储空间的方式 静态存储还是动态存储由变量的存储类别决定 存储类别分为四种 自动的 auto 、静态的 static 、寄存器的 register 、外部的 extern 格式存储类别关键字 类型关键字 标识符1,标识符2,...; 如 auto int a,b,c;

  34. 1. auto存储类 函数中的局部变量,凡不加存储类说明的都表示为auto类,即auto 可以缺省。如 int f(a) int a; {int b,c=3; ...} int f(a) auto int a; {auto int b,c=3; ...} 注auto类属于动态存储, 进入函数分配存储单元,退出函数系统收回存储单元

  35. 2.static存储类 static声明的变量属于静态存储,其用途让局部变量在退出它所在函数后仍保留存储单元,下一次进入该函数后,这些局部变量的值仍有效。称为静态局部变量。 例5-8阅读程序 运算 #include<stdio.h> void fun(int k) {int a=0; printf("%d, ",a); a=a+k; } void main() {int k; for(k=1;k<=3;k++) fun(k); } k a 输出 a+=k 1 0 0 0+1-->1 2 0 0 0+2-->2 3 0 0 0+3-->3 输出0, 0, 0,

  36. 例5-9阅读程序 运算 #include<stdio.h> void fun(int k) {static int a=0; printf("%d, ",a); a=a+k; } void main() {int k; for(k=1;k<=3;k++) fun(k); } k a 输出 a+=k 1 0 0 0+1-->1 2 1 1 1+2-->3 3 3 3 3+2-->5 输出0, 1, 3, 注:static型与auto型区别 存储单元分配: static分配固定存储空间 auto动态分配存储空间 存储单元缺省值:static为0 auto为随机值

  37. 3. register存储类 直接使用寄存器存储数据,提高运算速度,属于动态存储 例 阅读程序 一般小型机16个寄存器允 许3个作为register变量 个人微机13个寄存器没有 多余寄存器作为register变量 当定义的register变量超过 能使用的寄存器时自动转成 auto类变量。 #include<stdio.h> void fun(int k) {register int a=0; printf("%d, ",a); a+=k; } void main() {int k; for(k=1;k<=3;k++) fun(k); } 输出 0, 0, 0,

  38. 4. extern 变量 格式 extern [类型名] 变量名表; extern只是说明变量起作用,告诉C编译器该变量后面会定义。它不分配存储单元,所对应存储单元在变量定义处分配。 #include<stdio.h> void main() {int a; extern x; a=1; x=a; x=x+a; printf("%d\n",x); } int x; 声明x变量,在后定义 定义x是全局变量

More Related