1 / 63

主 讲:薄瑜 电 话 : 15233055176 email : cyyby2010@163

C 语言程序设计. 主 讲:薄瑜 电 话 : 15233055176 email : cyyby2010@163.com. 内容提要. 第 1 章 C 语言概述. 第 2 章 C 语言基本知识. 第 3 章 运算符和表达式. 第 4 章 顺序和选择结构程序设计. 第 5 章 循环结构程序设计. 第 6 章 函数. 第 7 章 数组. 第 8 章 指针. 第 9 章 结构体等构造数据类型. 第 10 章 文件. 6.1 函数基础 6.2 问题的提出与程序示例 6.3 函数的定义

chandler
Download Presentation

主 讲:薄瑜 电 话 : 15233055176 email : cyyby2010@163

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. C语言程序设计 主 讲:薄瑜 电 话:15233055176 email:cyyby2010@163.com

  2. 内容提要 第1章 C语言概述 第2章 C语言基本知识 第3章 运算符和表达式 第4章 顺序和选择结构程序设计 第5章 循环结构程序设计 第6章 函数 第7章 数组 第8章 指针 第9章 结构体等构造数据类型 第10章 文件

  3. 6.1 函数基础 6.2 问题的提出与程序示例 6.3 函数的定义 6.4 函数调用 6.5 函数说明 6.6 递归调用 6.7 变量的存储类别 第6章 函数 3/44

  4. §6.1 函数基础 函数:函数是实现某个功能的一段代码 C语言中,程序由若干个函数组成,每个程序只能有一个主函数(main函数)、其他函数都是子函数。 程序都从主函数main开始执行,调用完其它函数后又回到主函数,到main函数结束处终止执行。 各个子函数都是平行的、独立的。

  5. 输入 输出 §6.1 函数基础 • 使用函数的目的: (1)方便地使用其他人编写的代码 (2)在新程序中使用自己编写过的代码 (3)结构化程序设计的基本思想,将一个大型 程序分割成较小的、功能简单的、相对独立的程序

  6. §6.1 函数基础 • 从用户的角度看,可以分为: 库函数 用户自定义函数 • 从函数形式上看,可以分为: 有参函数:如putchar( )、sqrt( ) 无参函数: 如getchar( )

  7. §6.2 问题的提出与程序示例 先来看一个公式: m、n为整数,其中m>n。 • 问题如下: 考虑一下,是否有办法像调用库函数一样,调用自己设计过的求x!的程序,而不是全部重新编辑呢? 7/44

  8. §6.3 函数的定义 6.3.1 函数定义的形式 函数定义的一般形式 类型说明 函数名称 (带有类型说明的参数表) { 函数内部数据说明; 语句;} 无参函数的定义形式: 类型说明 函数名 () {函数体} void hello( ) { printf(“hello world!”); } 8/44

  9. 将求x!的程序写成一个自定义函数如右侧所示:将求x!的程序写成一个自定义函数如右侧所示: §6.3 函数的定义 有参函数的定义形式: 类型说明 函数名 (参数表) {函数体} int fac( int x) { int t=1,i=1; while(i<=x) { t=t*i; i++; } return t; } 9/44

  10. §6.3 函数的定义 函数名必须是合法标识符,且是用户定义字 函数定义中的函数体是用花括号括起来的语句。在函数体中,数据说明要放在执行语句的前面。 需要强调的是:函数定义中不能包含另一个函数的定义。 形式参数:定义函数时使用的参数,一定是变量,在上例中,形式参数是x。 10/44

  11. 6.3.2 函数的返回值 C语言中将函数分为带返回值和不带返回值的函数两种。 如果一个函数无返回值,此类函数用于完成某项特定的处理任务,函数的任务完成后不用返回结果,用户在定义此类函数时 §6.3 函数的定义 11/44

  12. 应指定它的返回值为“空类型”,空类型的说明符为“void”。 如果一个函数带有返回值,此类函数必须使用显示的返回语句,return语句向调用者返回一个结果,称为函数返回值。且必须在函数定义中明确指定返回值的数据类型。 §6.3 函数的定义 12/44

  13. return语句的主要功能:返回函数值,使程序回到调用该函数的语句的下一句执行。return语句的主要功能:返回函数值,使程序回到调用该函数的语句的下一句执行。 如果函数中没有明确地使用return语句,则系统自动隐含一个不带返回值的return语句。 §6.3 函数的定义 13/44

  14. 关于返回值,需要注意以下几点: return(表达式);return 表达式;均正确。 带有返回值的函数只能返回一个值。 在函数定义时,允许使用多个return语句,但不论执行到哪个都将返回到主函数。 return语句中的表达式与函数的返回值类型不匹配时,以函数定义时的返回值为准。 §6.3 函数的定义 14/44

  15. 例6.3 程序如下: §6.3 函数的定义 void nine( ) { int i,j; for(i=1;i<=9;i++) { for(j=1;j<=i;j++) printf("%d*%d=%d ",i,j,i*j); printf("\n"); } } 15/44

  16. §6.4 函数调用 6.4.1 函数的调用方式 格式如下: 函数名(参数表);例如:fac(5); 实际参数:调用函数时使用的参数,可以是变量、常量和运算符的表达式,函数调用时,实际参数的值被传给被调用函数的形式参数。 注意:实际参数的表达式前不能加数据类型说明。 16/44

  17. §6.4 函数调用 注意:实际参数的个数和数据类型、顺序必须与函数定义的形式参数的个数、数据类型、顺序匹配。 不带参数的函数,圆括号也不能省略 不带返回值的函数的调用方法是最简单的。函数调用一般作为独立的语句出现 带返回函数的调用方式有两种:一种是函数调用出现在表达式中;另一种是函数调用作为另一个函数的实参出现。 17/44

  18. 主函数 部分可 以写成 右面的 形式: §6.4 函数调用 #include "stdio.h" int fac( int n) { int t=1,i=1; while(i<=n) { t=t*i; i++; } return t; } void main( ) { int cmn,m,n; scanf("%d%d",&m,&n); cmn=fac(m)*fac(m-n)/fac(n); printf("cmn=%d\n",cmn); } 18/44

  19. §6.4 函数调用 例6.4 函数的调用形式 #include "stdio.h" int max(int x,int y) { if(x>y) return x; else return y; } void main() { int a,b,c; scanf("%d%d",&a,&b); c=max(a,b); printf("max num is %d\n",c); } int max(int b,int a) { if(b>a) return b; else return a; } 19/44

  20. §6.4 函数调用 • 例6.4 函数调用的流程 被调用函数 主调函数 main() {… c=max(a,b); … } int max(int x,inty) {… return x/y; } 传a,b 返回x/y 各函数间的信息往来是通过参数传递和返回语句实现的

  21. §6.4 函数调用 6.4.2 嵌套调用 C语言中,函数是一个一个并列的、独立的模块,并通过调用与被调用相关联。在一个函数定义中不可以定义另一个函数,但允许在一个函数中调用另一个函数。即函数定义不允许嵌套,但函数调用允许嵌套。 21/44

  22. §6.4 函数调用 #include "stdio.h" void printstar( ) { printf("****************\n"); } void printmessage( ) { printf("hello world\n"); printstar( ); } void main( ) { printstar( ); printmessage( ); }

  23. §6.4 函数调用 void printmassage() { printstar( ); } main( ) { printstar( ); printmessage(); } void printstar() { } 主调函数 被调用函数

  24. §6.5 函数说明 在程序中调用函数必须满足先定义后使用的原则 如果被调用的函数的位置出现在主函数之后需要对函数进行说明 函数说明的目的:是通知编译系统该函数已经定义过了。使编译系统知道被调用函数返回值的类型以及参数的类型,从而可以在调用函数中按照相应的类型作出相应的处理。

  25. §6.5 函数说明 函数说明的一般格式为: 返回值的数据类型 被调用函数名(形参表) 形参可以只给出类型,或者给出类型和形参名,函数说明语句的位置应该在函数定义之前。 25/44

  26. §6.5 函数说明 有两种情况,可以省略对被调用函数的说明: (1)被调用函数的函数定义出现在调用它的函数之前; (2)对C编译系统提供的库函数的调用不需要再做函数说明,但必须把该函数的头文件包含在源程序的最前面。 26/44

  27. §6.5 函数说明 #include "stdio.h " void printstar( ); void main( ) { printstar( ); } void printstar( ) { printf("****************\n"); }

  28. §总结 函数定义、函数调用和函数说明的职能。 (1)函数定义 函数定义,即定义函数的功能。未经定义的函数不能使用。 从定义的角度看,函数可以分为库函数和用户自定义函数两种。 库函数的定义有C编译系统提供,无需定义就可以使用。 用户定义函数是由程序员按照逻辑功能自己编写的函数。 28/44

  29. (2)函数说明 函数说明的功能是通知编译系统该函数已经定义过了。 库函数一般不用写函数说明,只要在程序前用#include命令包含具有该函数的头文件既可。 用户自定义函数,一般要在调用以前对被调用函数进行函数说明,然后才能调用,尤其当自定义函数的位置在调用它的语句之后时。 §总结 29/44

  30. (3)函数调用 函数调用是执行一个函数,调用函数时,程序跳转到被调用函数的第一句开始执行,执行到被调用函数的最后一句,然后程序返回到调用该函数处。 (4)return语句 函数的最后一句肯定是返回语句return,有些函数需要返回给调用它的函数一个值,有的则不需要返回值。 §总结 30/44

  31. n!= 递归调用的定义: 在一个函数定义中使用调用形式直接或间接地调用自己就称为递归调用。 应包含控制递归结束的条件。 §6.6 递归调用 1 n=0、1 n>1 n*(n-1)!

  32. 例6.10程序如下: §6.6 递归调用 32/44

  33. 例6.10是直接调用自身函数: §6.6 递归调用 参数n=3 n不等于0 输出3 调用f(3-1) 返回 参数n=2 n不等于0 输出2 调用f(2-1) 返回 参数n=1 n不等于0 输出1 调用f(1-1) 返回 void main() { f(3); } 参数n=0 n等于0 返回 33/44

  34. 编写递归程序的关键是: (1)构造递归表达式。 (2)寻找一个明确的递归结束条件,称为递归出口。 §6.6 递归调用 34/44

  35. §6.6 递归调用 • 桃子问题: 递推阶段 求解过程: 回推阶段 tao(1) =2*(tao(2)+1) tao(1) =94 tao(2) =2*(tao(3)+1) tao(2) =46 tao(3) =2*(tao(4)+1) tao(3) =22 tao(4) =10 tao(4) =2*(tao(5)+1) tao(5) =2*(tao(6)+1) tao(5) =4 tao(6) =1

  36. 用递归法计算n! 求n!可用下面的公式表示。 将n阶问题转换成n-1阶的问题,递归表达式为:f(n)=nf(n-1)。 §6.6 递归调用 1 (n=0或n=1) n(n-1)! (n>1) f= 36/44

  37. 例6.11 求n!函数如下: §6.6 递归调用 37/44

  38. 例6.11 求n!主函数如下: §6.6 递归调用 38/44

  39. 变量的作用域是指变量的作用范围,根据作用域不同,变量分为全局变量和局部变量。变量的作用域是指变量的作用范围,根据作用域不同,变量分为全局变量和局部变量。 局部变量: 1.在函数内定义的变量 2.函数的形式参数 3.在某个复合语句内定义的变量 注意: 1.局部变量只在自己的范围内有效 2.如果局部变量的有效范围有重叠,则有效范围小的优先。 §6.7 变量的存储类别 int f1( float a) { float i,j; …… } main( ) { int a,b,c; …… } void main( ) { float i,j; …… { int d,i; …… d=i+j; } } int f1( float a) { float i,j; …… } float f2(int x,int y) { int a,b,c; …… } void main( ) { float i,j; …… { int d; …… d=i+j; } } a有效 i,j有效 i有效 局部优先 d有效 x,y有效 a,b,c有效 39/44

  40. 变量的作用域是指变量的作用范围,在C语言中,变量的作用域分为全局有效、局部有效两种。变量的作用域是指变量的作用范围,在C语言中,变量的作用域分为全局有效、局部有效两种。 全局变量:在函数之外定义的变量 全局变量的有效范围是:从定义变量的位置开始到源文件结束 在一个函数中既可以使用本函数的局部变量,也可以使用有效的全局变量 §6.7 变量的存储类别 int m,n int f1( float a) { float i,j; } main( ) { int a,b,c; } m,n有效 40/44

  41. 作用:利用全局变量可以在函数间传递数据 题目:已知一长方体的长、宽、高,求长方体的体积、三个面的面积。 分析:用一个函数返回1个值,还可以借助全局变量得到其余3个值。 尽量少用全局变量。 全局变量和局部变量同名,局部变量优先。 §6.7 变量的存储类别 int s1,s2,s3; int vs(int a,int b,int c) { int v; v=a*b*c; s1=a*b; s2=a*c; s3=b*c; return v; } main( ) { int v,l,w,h; scanf(“%d%d%d”,&l,&w,&h); v=vs(l,w,h); printf(“%d,%d,%d,%d”,v,s1,s2,s3); } int a=3,b=5; int max(int a,int b) { int c; c=a>b?a:b; return c; } main( ) { int a=8; printf(“max=%d”,max(a,b)); } 41/44

  42. 内存中供用户使用的存储空间包括: 程序区 静态存储区中的变量是从程序开始执行到程序结束这段时间,始终拥有自己已经分配了的固定的存储空间。 动态存储区中的变量是在程序运行期间根据需要随时进行动态分配的存储空间。 §6.7 变量的存储类别 42/44

  43. 一个变量,除要进行类型说明以外,还要说明变量的存储类别。一个变量,除要进行类型说明以外,还要说明变量的存储类别。 变量的四种存储类别为:自动变量(auto)、寄存器变量(register)、静态变量(static)和外部变量(extern)。 由于变量存储类别不同而产生的存在时间不同的特性称为变量的生存期。变量的生存期表示了变量作用时间的长短。 §6.7 变量的存储类别 43/44

  44. 外部变量和静态变量存放在静态存储区中,在程序开始执行时分配固定的存储区,整个程序执行完毕才释放。外部变量和静态变量存放在静态存储区中,在程序开始执行时分配固定的存储区,整个程序执行完毕才释放。 寄存器变量和自动变量存放在动态存储区中,在程序开始时分配动态存储空间,程序结束时释放这些空间。 §6.7 变量的存储类别 44/44

  45. 6.8.1 自动变量与外部变量 自动变量 自动变量是存放在动态存储区的,定义自动变量时,可用在数据类型名前加上关键字auto,也可以省略。 §6.7 变量的存储类别 int fac1(int a,int b) { auto int c=3; } 45/44

  46. 函数调用时数据的传递是单向值传递。 形参标识了一个存储空间的变量名,这个存储空间是在函数被调用时由系统分配的,被调用函数执行完毕,则形参的空间将被系统释放。 鉴于以上原因,当实参是一个变量名时,被调用函数内的形参的值无论如何变化,都不会影响实参的变化。 §6.6 参数传递 46/44

  47. §6.6 参数传递 #include "stdio.h " int sum(int a,int b) { a=a+b; b=a+b; return a; } void main( ) { int a,b,c; c=sum(a,b); printf(“sum of %d and %d is %d”,a,b,c) }

  48. 作用域在函数外的全局变量叫外部变量,外部变量存储在静态存储区中作用域在函数外的全局变量叫外部变量,外部变量存储在静态存储区中 外部变量的声明: (1)语法格式为:extern 数据类型 变量名。 (2)变量的定义和说明的区别:变量说明是说明变量的特性(存储长度和类型等);变量定义除了说明变量的特性,还要分配存储空间。 §6.7 变量的存储类别 int a=3,b=5; void f1( ) { extern int x; } float x,y; main( ) { …… } F1.cpp int a,b; void main() { …… } F2.cpp extern int a,b; func() { …… } 48/44

  49. 6.8.2 静态变量 静态变量的类型标识是static,静态变量可以分为局部静态变量和全局静态变量。 局部静态变量的特点: 1.局部静态变量属于静态存储类别,在整个程序运行期间都不释放内存。 2.局部静态变量在编译时仅赋一次初值。 3.如果定义时没有赋初值,编译时会自动赋初值. 4.局部静态变量只能在定义它的函数内使用。 §6.7 变量的存储类别 #include “stdio.h” void f( ); void main() { int i; for(i=1;i<=5;i++) f( ); } void f( ) { int j=0; ++j; printf(“%d”,j); } auto static 49/44

  50. §6.7 变量的存储类别 F1.cpp static int a,b; void main() { …… } F2.cpp extern int a,b; func() { …… } • 6.8.2 静态变量 • 全局变量本身是静态存储方式,静态全局变量当然也是静态存储方式。 • 全局变量和静态全局变量的区别: 非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都有效,而静态全局变量则限制了它的作用域,即只在定义该变量的源文件内有效。 即使做了外部变量声明也不能在f2.cpp中使用a、b

More Related