1 / 33

第八章 函数

第八章 函数. 8.1 函数概述 8.2 函数定义的一般形式 8.3 函数参数和函数的值 8.4 函数的调用 8.5 函数的嵌套调用 8.6 函数的递归调用 8.7 数组作为函数参数 8.8 局部变量和全局变量. #include &lt;stdio.h&gt; #include &lt;math.h&gt; void main ( ) { int a, b, c; scanf (“%d%d”, &amp;a, &amp;b) ; c=a+ abs (b); printf (“c=%d<br>”, c); }. 8.1 函数概述. 一、有关 C 函数的介绍

erasto
Download Presentation

第八章 函数

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. 第八章 函数 • 8.1 函数概述 • 8.2 函数定义的一般形式 • 8.3 函数参数和函数的值 • 8.4 函数的调用 • 8.5 函数的嵌套调用 • 8.6 函数的递归调用 • 8.7 数组作为函数参数 • 8.8 局部变量和全局变量

  2. #include <stdio.h> #include <math.h> void main( ) { int a, b, c; scanf(“%d%d”, &a, &b) ; c=a+abs(b); printf(“c=%d\n”, c); } 8.1 函数概述 • 一、有关C 函数的介绍 • 一个源程序文件由一个 • 或多个函数组成 2. 一个C程序由一个或多个 源程序文件组成 3. C程序从main函数开始执行, 调用其他函数后再返回到main 函数 4. 所有函数都是平行的, 定义函数时是互相独立的, 函数之间可以互相调用, 但是不能调用main函数

  3. 二、C 函数的分类 1. 从用户使用角度分为: 标准函数和用户自定义函数 2. 从函数的形式分为: 无参函数和有参函数 函数定义 #include <stdio.h> void main( ) { printf(“******\n”); printf(“ good \n”); printf(“******\n”); } /*printf是标准函数*/ #include <stdio.h> void list(void) { printf(“******\n”); } void main( ) { list( ) ; printf(“ good \n”); list ( );/*用户自定义 函数*/ } #include <stdio.h> int max(int x, int y) { int z ; if (x>y) z=x ; else z=y ; return(z) ; } void main( ) { int a ,b ,c ; scanf(“%d%d”,&a,&b); c=max(a,b); printf(“max=%d”,c); } 形式参数 函数调用 实在参数

  4. 8.2函数定义的一般形式 1. 定义格式 : 函数类型 函数名 ( 形式参数表) { 函数体 ; } 2. 说明 (1) 函数名 : 用户定义的合法标识符 (2) 函数的类型 : 函数返回值的类型 若返回值为 int 或char 类型, 函数定义时可省略不写 若函数无返回值, 函数定义时应写上 void 类型 void list(void) { printf(“******\n”); }

  5. (3) 形式参数 ① 书写格式 : 每一个参数都要写上数据类型和参数名 参数之间以逗号分隔, 无参数时一般写上void 声明它为空 ② 作用 : 表示将从主函数中接收哪些类型的信息 例 : int max( int x , int y ) { int z ; z = x > y ? x : y ; return( z ) ; } (4) 函数体: 由变量声明和语句组成 ① 函数体内定义的变量是局部量, 只在执行该函数时存在 ② 函数体可以为空(即存在空函数) void f (void) { }

  6. 8.3 函数参数和函数的值 一、形式参数和实在参数 1. 形式参数 : 在定义函数时写在函数名后面的括号内的变量 2. 实在参数: 在调用函数时写在函数名后面的括号内的变量 • 3. 说明 • 程序在编译时不为形参分配存储空间, 只有当函数 • 被调用时, 形参被分配存储空间, 在调用结束后, 形参 • 所占的空间被释放 • (2) 实参可以是常量, 变量或表达式 • (3) 实参和形参的类型应相同或赋值相容 • (4) 实参对形参的数据传递是“值传递”, 即单向传递 • 实参  形参

  7. 二、 函数的返回值 1. 函数的返回值通过函数中return语句获得 return语句的作用: 使流程返回主调函数 ; 将函数值送回到调用表达式中 2. 函数类型决定函数返回值的类型 一般函数值的类型和return语句中表达式的类型应一致 如果二者不一致, 则以函数值的类型为准 3. 有的函数中没有return语句, 因为它不需要带回值, 这时 可以将函数类型定义为 void 型 void list(void) { printf(“******\n”); }

  8. 4. 一个函数允许有一个或多个return语句, 但每个return 后的表达式类型要相同; 当执行到其中任何一个return 语句时会立即返回主调函数 int fun( int n ) { if ( n >10 ) return( n ) ; else return( 2*n ) ; }

  9. 8.4 函数的调用 一、函数调用 1. 一般形式 : 函数名( 实参表列 ) ; 2. 说明 (1) 实参表列可以包含多个实参, 各个实参之间用逗号分隔 (2) 实参与形参的个数应相等, 类型一致, 顺序要一一对应 (3) 调用无参函数时格式为 : 函数名( )注意( )不能省略 (4) BC31中按从左至右的顺序对实参求值 3. 函数调用的方式 (1) 函数语句printf(“hello!”) ; /*标准函数调用*/ (2) 函数表达式 c = 2 * max( a , b ) ; /*自定义函数调用*/ (3) 函数参数 m = max ( c , max ( a , b ) ) ;

  10. 4. 函数调用过程 : (1) 形参与实参各自占有一个独立的存储空间 (2) 形参的存储空间在函数被调用时才分配 (3) 函数返回时, 形参占据的临时存储区被撤消 特点 : 函数中对形参变量的操作不会影响到实参 #include <stdio.h> int f (int x , int y) { x = x+2 ; y = y*2 ; return( x+y ) ; } void main ( ) { int a , b , c ; scanf(“%d%d” , &a , &b) ; c = f(a , b) ; printf(“%d\t” , c) ; printf(“%d,%d\n”,a,b); } 假设输入为: 3 5 f 函数 main函数 a 5 x 3 3 10 y b 5 5 c 15 运行结果为:15 3 , 5

  11. 二、函数声明 1. 在调用函数前, 一般要对函数事先作出声明 声明有利于编译系统对函数调用的合法性进行检查 2. 声明格式 : 函数类型 函数名 ( 形参表 ); C程序的一般格式: # 命令 函数声明 main函数的定义 其他函数的定义 3. 注意事项: (1)函数声明末尾要加分号 (2) 形参表中可以只写数据类型 如 int f ( int , float ) ; (3)形参的先后次序不能写错 (4) 当被调用的函数定义写在主调函数 之前时, 允许省略函数声明 (5) 建议将程序中用到的函数都在程序的前面加以声明

  12. 4. 声明的位置 : (1) 在main 函数中声明 (2) 所有函数进行外部声明 函数声明 函数声明 #include <stdio.h> int f (int x , int y); void main ( ) { int a , b , c ; scanf(“%d%d”, &a, &b); c = f(a , b) ; printf(“%d\n” , c) ; } int f (int x , int y) { x = x+2 ; y = y*2 ; return( x+y ) ; } #include <stdio.h> void main ( ) { int f (int x , int y); int a , b , c ; scanf(“%d%d”, &a, &b) ; c = f(a , b) ; printf(“%d\n” , c) ; } int f (int x , int y) { x = x+2 ; y = y*2 ; return( x+y ) ; } 函数定义 函数定义

  13. 例 : 求100-200间的素数 函数定义 int prime( int n ) { int i , k , flag=1 ; k=sqrt(n); for(i=2 ; i<=k ; i++) if(n%i==0) { flag=0 ; break ; } return(flag); } 若m为素数则返回值为 1;否则返回值为0 #include <stdio.h> #include <math.h> int prime( int n ) ; void main( ) { int m , p , num=0 ; for (m=101 ; m<=200 ; m=m+2) {p=prime(m); if (p==1) { printf(“%5d”, m ); num++ ; } } printf(“\n num=%d \n”, num); } 函数声明 函数调用

  14. 调用 嵌套 调用 调用 8.5 函数的嵌套调用 C语言规定函数定义都是平行的、独立的, 即函数不能 进行嵌套的定义, 但是函数可以进行嵌套调用. 函数的嵌套调用是指在调用一个函数的过程中调用另 一个函数. main函数 void main( ) { : fun( ) ; : } void fun( void ) { : g( ) ; : } fun函数 g函数

  15. #include <stdio.h> void fa (void) { putchar( ‘a’ ) ; } void fb (void) { fa( ) ; putchar( ‘ t’ ) ; } void main (void) { putchar( ‘c’ ); fb( ) ; } main fb fa 输出a 输出c 调用fa 结束 调用fb 输出t 结束 结束 输出结果: cat

  16. 8.6 函数的递归调用 1. 函数递归调用的概念: 在调用一个函数的过程中又直接 或间接地调用该函数自己 2.用递归求解问题的特点 (1)存在某个特定条件,在此条件下可以得到指定的解. (即:递归的终止条件) (2)对任意给定的条件有明确的定义规则,可以产生新的 状态,并将最终导出终止状态. (即:存在导致问题求解的递归方式) 3. 优点 : 程序简洁, 代码紧凑 缺点 : 占用存储空间较多, 时间效率较差

  17. 1 n=0,1 n*(n-1) ! n>0 n!= 调用 例: 用递归的方法求n! 递归的终止条件 递归方式 主调函数 返回值24 4!=4*(4-1)! 返回值6 3!=3*(3-1)! 返回值2 2!=2*(2-1)! 返回值1 1!=1

  18. #include <stdio.h> float fac( int n ) ; void main( ) { int m ; float y ; scanf(“%d”, &m ); y=fac(m); /*调用函数fac ()*/ printf(“%d!=%15.0f \n”, m , y ) ; } float fac(int n) { float f ; if ( n<0 ) { printf(“error!”); f=-1; } else if (n==0 || n==1 ) f=1; else f=n*fac( n-1 ) ;/*递归调用自己*/ return(f ) ; } 函数声明 函数定义 递归调用

  19. 递归调用过程: 调用fac mn ③ 调用fac mn ② 调用fac mn ① main函数 输入m ③ 因3!=0,1 f=3*fac(3-1) 因2!=0,1 f=2*fac(2-1) 因1==1 f=1 y=fac(m) 输出y ⑥ 返回f ⑥ 返回f ② 返回f ① 结束

  20. 8.7 数组作为函数参数 一、数组元素作函数参数(值传递) 其用法与变量作实在参数一样,实参和形参都使用不同 的数组内容,是单向传递 二、数组名作函数参数(地址传递) 实参和形参都使用同一数组内容。 说明: 1. 必须在主调函数和被调函数中分别定义数组 2. 实参数组和形参数组的类型必须一致 3. 数组名作参数实际上是将实参数组的首地址传给形参 数组, 即实参数组和形参数组占用同一片内存单元 4.数组名作参数时,定义形参数组时可以不指定其大小 , 当形参数组发生变化时, 实参数组也随之发生变化

  21. 例:求某班成绩的平均分 #include <stdio.h> float average(int s[40]); void main( ) { int i , sc[40] ; float aver ; for(i=0; i<=39 ; i++) scanf(“%d”,&sc[i]); aver=average(sc);/*数组名作参数*/ printf(“aver=%f”, aver); } float average(int s[40]) { int sum , i ; float ave ; sum=0; for(i=0; i<=39 ; i++) sum=sum+s[i]; ave=sum/40; return(ave); } #include <stdio.h> void main( ) { int i , sum , s[40] ; float ave ; for(i=0; i<=39 ; i++) scanf(“%d”,&s[i]); sum=0; for(i=0; i<=39 ; i++) sum=sum+s[i]; ave=sum/40; printf(“ave=%f”, ave); }

  22. 数组占用 存储空间 main 调用average scs main average sc[0] sc[1] sc[2] : : : : sc[39] 78 84 90 : : : : 66 s[0] s[1] s[2] : : : : s[39] 输入sc的 40个元素 sum=0 aver=average(sc) 计算sum 输出aver ave=sum/40 结束 返回ave的值

  23. 例: 选择排序 #include <stdio.h> void sort ( inta[ ], intn); void main( ) { int b[6] , i ; for ( i=0 ; i<6 ; i++) scanf(“%d”, &b[i] ) ; sort( b , 6 ); /*数组名作参数*/ for ( i=0 ; i<6 ; i++) printf( “%3d”, b[i] ) ; } #include <stdio.h> void main( ) { int a[6] , i , j , k , t; for ( i=0 ; i<6 ; i++) scanf(“%d”, &a[i] ); for ( i=0 ; i<5 ; i++) { k=i ; for ( j=i+1 ; j<6 ; j++) if ( a[k]>a[j] ) k=j ; if ( k!=i ) { t=a[i] ; a[i]=a[k] ; a[k]=t ; } } for ( i=0 ; i<6 ; i++) printf( “%3d”, a[i] ); } voidsort ( int a[ ] , int n) { int i , j , k , t ; for ( i=0 ; i<n-1 ; i++) { k=i ; for ( j=i+1 ; j<n ; j++) if ( a[k]>a[j] ) k=j ; if ( k!=i ) { t=a[i] ; a[i]=a[k] ; a[k]=t ; } } }

  24. 8.8 局部变量和全局变量 一、局部变量: 指在一个函数内部定义的变量, 它只在本 函数的范围内有效, 在此函数之外不能使用这些变量 说明: 1. main函数中定义的变量是局部变量, 它们只能在main函数中使用 2. 不同函数中可以使用相同名字的变量,它们互不干扰 3. 形式参数也是局部变量 4. 在复合语句中定义的变量, 它们只在复合语句内有效

  25. #include <stdio.h> void sort ( int a[ ] , int n); void main( ) { int b[6] , i ; for ( i=0 ; i<6 ; i++) scanf(“%d”, &b[i] ) ; sort( b , 6 ); for ( i=0 ; i<6 ; i++) printf( “%3d”, b[i] ) ; } main函数中的局部变量:b和 i 参数a和n也是局部变量 void sort ( int a[ ] , int n) { int i , j , k ; for ( i=0 ; i<n-1 ; i++) { k=i ; for ( j=i+1 ; j<n ; j++) if ( a[k]>a[j] ) k=j ; if ( k!=i ) { int t ; t=a[i] ; a[i]=a[k] ; a[k]=t ; } } } sort函数中的局部变量: i , j, k t 是复合语句中的局部变量, 只能以下在3个赋值语句中使用

  26. 全局变量p和 q的有效范围 全局变量数组 s的有效范围 全局变量m和 n的有效范围 二、全局变量: 指在所有函数之外定义的变量( 外部变量) , 它的有效范围从定义变量的位置开始到本源文件结束 #include <stdio.h> int p=1 , q=5 ; float f1( int a ) { float r ; : } int s[10] ; int f2( int b , int c ) ; { int sum ; : } float m , n ; void main( ) { float x , y ; : }

  27. 1. 全局变量的使用增加了函数间数据联系的渠道 由于在同一文件中的所有函数都能使用全局变量, 所以 可以利用全局变量从函数中得到一个以上的返回值 例: 求某班成绩的平均分, 最高分和最低分 #include <stdio.h> int max , min ; float average( int s[ ] ); void main( ) { int i , sc[40] ; float aver ; for(i=0; i<=39 ; i++) scanf(“%d”,&sc[i]); aver=average(sc); printf(“aver=%f\n”, aver); printf(“max=%d\n”, max); printf(“min=%d\n”,min); } float average( int s[ ] ) { int sum , i ; float ave ; sum=0; max=min=s[0]; for(i=0; i<=39 ; i++) { sum=sum+s[i]; if (s[i]>max) max=s[i]; else if ( s[i]<min ) min=s[i]; } ave=sum/40; return(ave); }

  28. 2. 建议不要过多的使用全局变量 (1) 全局变量在程序的执行过程中一直占用存储单元 (2) 它使函数的通用性降低 (3) 它会降低程序的清晰性 #include <stdio.h> int x=10; void f(void) { int x=1; x=x+1; printf(“x=%d\n”, x ); } void main() { x=x+1; printf(“x=%d\t”, x); f( ); } 3. 在一个源文件中如果局部变量 和全局变量同名, 在局部变量 起作用的范围内, 全局变量 不起作用 输出结果: x=11 x=2

  29. 课后作业: P186 8.1、 8.3、 8.5 8.15、8.16

  30. 练习8.10 思路:找长度最大的单词,必须记录每一个单词的字母个数,取最大值;并将找到的单词输出。 步骤: 主程序:1、从键盘上输入一行字符,存入一字符数组str中; 2、调用一函数maxstr(),得到字符串中长度最大的单词; 3、将结果输出。 函数maxstr():1、设一个变量len存放最长单词的长度,其初始值为0; 2、从字符串最左边开始,获得每一个单词的长度(即遇到一个空格时,其前面为一个单词,用一个变量记录单词长度),与len比较,若大于,则将其值赋予len,将此单词传送给另一数组str1;循环直到整个字符串执行完为止。 在此最好将str1定义为全局变量,使得在函数maxstr()中得到的值,在主程序中也可以使用。

  31. #include "stdio.h" char str1[10]; maxstr(char a[50] , int n) ; main() { char str[50],danci[10]; int i,dlen; printf("\n input a string:"); gets(str); dlen=strlen(str); maxstr(str,dlen); printf("\nThe max word="); puts(str1); }

  32. maxstr(char a[50],int n) { int i,len,j,m,x; len=0; i=0; while(i<=n) { j=0; while((a[i]!=' ')&&(i<=n)) { j++; i++; } if (j>len) { len=j; x=0;

  33. for(m=i-j;m<=i;m++) { str1[x]=a[m]; x++; } str1[x]='\0'; } i++; } }

More Related