c语言程序设计现代方法课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《c语言程序设计现代方法课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言程序设计 现代 方法 课件
- 资源描述:
-
1、第9章:函数c语言程序设计现代方法Copyright 2008 W.W.Norton&Company.All rights reserved.1第9章:函数本章要点第9章:函数概述 函数简单来说就是一连串组合在一起并且命名的语句。每个函数本质上是一个自带声明和语句的小程序。函数的优点:可以利用函数把程序划分成小块,这样便于人们理解和修改程序。可以避免重复编写可多次使用的代码。一个函数最初可能是某个程序的一部分,但可以将其用于其他程序中。3第9章:函数函数的定义和调用 在介绍定义函数的规则之前,先来看3个简单的定义函数的程序。4第9章:函数程序:计算平均值 一个叫做average的函数用来计算两
2、个double类型数值的平均值:double average(double a,double b)return(a+b)/2;在函数开始处放置的单词double表示了average函数的返回类型(return type)。标识符a和标识符b(即函数的形式参数(parameter)表示在调用average函数时提供的求平均值的两个数。5第9章:函数程序:计算平均值 每个函数都有一个用大括号括起来的执行部分,称为函数体(body)。average函数的函数体由一条return语句构成。执行这条语句将会使函数“返回”到调用它的地方,表达式(a+b)/2的值将作为函数的返回值。6第9章:函数程序:计算
3、平均值 一个函数调用包括函数名和其后的实际参数(arguments)列表。average(x,y)即为对average函数的调用。实际参数用来给函数提供信息。调用average(x,y)的效果就是把变量x和y的值复制给形式参数a和b。实际参数不一定要是变量;任何正确类型的表达式都可以。average(5.1,8.9)和 average(x/2,y/3)都是合法的。7第9章:函数程序:计算平均值 我们把average函数的调用放在需要使用其返回值的地方。打印x和y平均值的语句为:printf(Average:%gn,average(x,y);average的返回值没有保存;程序显示出这个值后就把
4、它丢弃了。如果需要在稍后的程序中用到返回值,可以把这个返回值赋值给变量:avg=average(x,y);8第9章:函数程序:计算平均值 程序average.c读取了3个数并且计算它们的平均值,其中,一次计算一对数的平均值:Enter three numbers:3.5 9.6 10.2Average of 3.5 and 9.6:6.55Average of 9.6 and 10.2:9.9Average of 3.5 and 10.2:6.859第9章:函数average.c/*Computes pairwise averages of three numbers*/#include do
5、uble average(double a,double b)return(a+b)/2;int main(void)double x,y,z;printf(Enter three numbers:);scanf(%lf%lf%lf,&x,&y,&z);printf(Average of%g and%g:%gn,x,y,average(x,y);printf(Average of%g and%g:%gn,y,z,average(y,z);printf(Average of%g and%g:%gn,x,z,average(x,z);return 0;10第9章:函数程序:显示倒数计数 为了指示出
6、不带返回值的函数,需要指明这类函数的返回类型为void:void print_count(int n)printf(T minus%d and countingn,n);void是一种没有值的类型。print_count函数的调用必须自成一个语句:print_count(i);程序countdown.c在循环内调用了print_count 函数10次。11第9章:函数countdown.c/*Prints a countdown*/#include void print_count(int n)printf(T minus%d and countingn,n);int main(void)in
7、t i;for(i=10;i 0;-i)print_count(i);return 0;12第9章:函数程序:显示双关语(改进版)当函数没有形式参数时,则在函数名后面的圆括号中填入 void:void print_pun(void)printf(To C,or not to C:that is the question.n);为了调用不带实际参数的函数,需要写出函数名并且后面跟上一对圆括号:print_pun();即使没有实际参数也必须显示圆括号。程序pun2.c测试了print_pun函数。13第9章:函数pun2.c/*Prints a bad pun*/#include void pri
8、nt_pun(void)printf(To C,or not to C:that is the question.n);int main(void)print_pun();return 0;14第9章:函数函数定义 函数定义函数定义的一般格式:返回类型 函数名(形式参数)声明 语句15第9章:函数函数定义 函数的“返回类型”是函数返回值的类型。下列规则用来管理返回类型:函数无法返回数组。指定返回类型是void型说明函数没有返回值。在C89中,如果忽略返回类型,那么会假定函数返回值的类型是int型。在C99中,忽略返回类型是非法的。16第9章:函数函数定义 一些程序员习惯把返回类型放在函数名的上
9、边:doubleaverage(double a,double b)return(a+b)/2;如果返回类型很冗长,比如unsigned long int类型,那么把返回类型单独放在一行是非常有用的。17第9章:函数函数定义 函数名后边有一串形式参数列表。每个形式参数需要说明其类型;形式参数间用逗号进行分隔。如果函数没有形式参数,那么在圆括号内应该出现void。18第9章:函数函数定义 函数体可以包含声明和语句。average函数的变体:double average(double a,double b)double sum;/*declaration*/sum=a+b;/*statement*
10、/return sum/2;/*statement*/19第9章:函数函数定义 函数体内声明的变量专属于此函数,其他函数不能对这些变量进行检查或修改。在C89中,变量声明必须出现在语句之前。在C99中,变量声明和语句可以混在一起,只要变量在第一次使用前进行声明即可。20第9章:函数函数定义 返回类型为void的函数(“void 函数”)的函数体可以为空:void print_pun(void)在程序开发过程中,作为一种临时措施,留下空函数体是有意义的。21第9章:函数函数调用 函数调用由函数名和跟随其后的实际参数列表组成,其中实际参数列表用圆括号括起来:average(x,y)print_co
11、unt(i)print_pun()如果丢失圆括号,那么将无法进行函数调用:print_pun;/*WRONG*/这条语句是合法的,但是不起作用。22第9章:函数函数调用 void型的函数调用是语句,所以调用后边始终跟着分号:print_count(i);print_pun();非void型的函数调用产生的值可存储在变量中,还可以进行测试、显示或者其他用途:avg=average(x,y);if(average(x,y)0)printf(Average is positiven);printf(The average is%gn,average(x,y);23第9章:函数函数调用 如果不需要,非
12、void型函数的返回值总是可以丢弃:average(x,y);/*discards return value*/这个调用是一个表达式语句的示例:一个计算出了表达式值但是将其丢弃的语句。24第9章:函数函数调用 丢弃average的返回值是一件很奇怪的事,但在某些情况下是有意义的:例如:printf返回显示的字符的个数。在下面的调用后,num_chars的值为9:num_chars=printf(Hi,Mom!n);通常会丢掉printfs的返回值:printf(Hi,Mom!n);/*discards return value*/25第9章:函数函数调用 为了清楚地表示故意丢掉函数返回值,C语
13、言允许在函数调用前加上(void):(void)printf(Hi,Mom!n);使用(void)可以使别人清楚编写者是故意扔掉返回值的,而不是忘记了。26第9章:函数程序:判定素数 程序prime.c检查一个数是否是素数:Enter a number:34Not prime 程序使用名为is_prime的函数来进行检查。该函数返回值为true就表示它的形式参数是素数,返回false就表示它的形式参数不是素数。给定数n后,is_prime函数把n除以从2到n的平方根之间的每一个数:如果余数永远为0,就知道n不是素数。27第9章:函数prime.c/*Tests whether a number
14、 is prime*/#include /*C99 only*/#include bool is_prime(int n)int divisor;if(n=1)return false;for(divisor=2;divisor*divisor=n;divisor+)if(n%divisor=0)return false;return true;28第9章:函数int main(void)int n;printf(Enter a number:);scanf(%d,&n);if(is_prime(n)printf(Primen);else printf(Not primen);return 0
15、;29第9章:函数函数声明 C语言没有要求函数的定义必须放置在调用它之前。假设重新编排程序average.c,使average函数的定义放置在main函数的定义之后:30第9章:函数函数声明#include int main(void)double x,y,z;printf(Enter three numbers:);scanf(%lf%lf%lf,&x,&y,&z);printf(Average of%g and%g:%gn,x,y,average(x,y);printf(Average of%g and%g:%gn,y,z,average(y,z);printf(Average of%g
16、and%g:%gn,x,z,average(x,z);return 0;double average(double a,double b)return(a+b)/2;31第9章:函数函数声明 当遇到main函数中第一个average函数调用时,编译器没有任何关于average函数的信息。但是,编译器没有产生错误信息,而是假设average函数返回int型的值。我们将其称为编译器为该函数创建了一个隐式声明(implicit declaration)。32第9章:函数函数声明 编译器无法检查传递给average的实参个数和实参类型是否正确。它只能进行默认的实际参数提升并期待最好情况的发生。当编译器
17、在后面遇到了average的定义时,它发现该函数返回值实际是double而非int,结果我们将得到一条错误消息的提示。33第9章:函数函数声明 为了避免定义前调用这类问题的发生,一种方法是安排程序,使每个函数的定义都在此函数调用之前进行。可惜的是,这类安排不总是存在的。而且即使真的做了这类安排,也会因为按照不自然的顺序放置函数定义,使程序难以阅读。34第9章:函数函数声明 幸运的是,C语言提供了一种更好的解决办法:在调用前声明(declare)每个函数。函数声明(function declaration)使得编译器对函数进行概要浏览,而函数的完整定义稍后再出现。函数声明的一般形式:返回类型 函
18、数名(形式参数);函数的声明必须与函数的定义一致。下面是为average函数添加了声明后程序的样子:35第9章:函数函数声明#include double average(double a,double b);/*DECLARATION*/int main(void)double x,y,z;printf(Enter three numbers:);scanf(%lf%lf%lf,&x,&y,&z);printf(Average of%g and%g:%gn,x,y,average(x,y);printf(Average of%g and%g:%gn,y,z,average(y,z);prin
19、tf(Average of%g and%g:%gn,x,z,average(x,z);return 0;double average(double a,double b)/*DEFINITION*/return(a+b)/2;36第9章:函数函数声明 我们把正在讨论的这类函数声明称为函数原型(function prototype)。C语言还有一种老式的函数声明风格,即圆括号内可以留空。函数原型不需要说明函数形式参数的名字,只要显示它们的类型就可以了:double average(double,double);通常最好是不要忽略形式参数的名字。37第9章:函数函数声明 C99遵循这样的规则:在调
20、用一个函数之前,必须先对其进行声明或定义。调用函数时,如果此前编译器未见到该函数的声明或定义,会导致出错。38第9章:函数实际参数 在C语言中,实际参数是通过值传递的:调用函数时,计算出每个实际参数的值并且把它赋值给相应的形式参数。在函数执行过程中,对形式参数的改变不会影响实际参数的值,这是因为形式参数中包含的是实际参数值的副本。39第9章:函数实际参数 实际参数按值传递既有利也有弊。既然形式参数的修改不会影响到相应的实际参数,那么可以把形式参数作为函数内的变量来使用,因此可以减少真正需要的变量的数量。40第9章:函数实际参数 思考下面这个函数,此函数用来计算数x的n次幂:int power(
21、int x,int n)int i,result=1;for(i=1;i 0)result=result*x;return result;42第9章:函数实际参数 C语言关于实际参数按值传递的要求使它很难编写某些类型的函数。假设我们需要一个函数,它将把double型的值分解成整数部分和小数部分。因为函数无法返回两个数,所以可以尝试把两个变量传递给函数并且修改它们:void decompose(double x,long int_part,double frac_part)int_part=(long)x;frac_part=x-int_part;43第9章:函数实际参数 假设采用下面的方法调用
22、这个函数:decompose(3.14159,i,d);可惜的是,变量i和d不会因为赋值给int_part和frac_part而受到影响。第11章中将阐述如何使decompose函数正确地工作。44第9章:函数实际参数的转换 C语言允许在实际参数的类型与形式参数的类型不匹配的情况下进行函数调用。管理如何转换实际参数的规则与编译器是否在调用前遇到函数(或者函数的完整定义)的原型有关:45第9章:函数实际参数的转换 编译器在调用前遇到原型。编译器在调用前遇到原型。就像使用赋值一样,每个实际参数的值被隐式地转换成相应形式参数的类型。例如:如果把int类型的实际参数传递给期望得到double型数据的函
23、数,那么会自动把实际参数转换成double类型。46第9章:函数实际参数的转换 编译器在调用前没有遇到原型。编译器在调用前没有遇到原型。编译器执行默认的实际参数提升默认的实际参数提升:把float型的实际参数转换成double类型。执行整数的提升,即把char型和short型的实际参数转换成int型(在C99中实现了整数提升)。47第9章:函数实际参数的转换依赖默认的实际参数提升是危险的。例如:#include int main(void)double x=3.0;printf(Square:%dn,square(x);return 0;int square(int n)return n*n;
24、在调用square函数时,编译器没有遇到原型,所以不知道该函数期望有int类型的实际参数。48第9章:函数实际参数的转换 取而代之的,编译器在变量x上执行了没有效果的默认的实际参数提升。因为square函数期望有int类型的实际参数,但是却获得了double类型值,所以square函数将产生无效的结果。把squares的实际参数强制转换为正确的类型可解决这个问题:printf(Square:%dn,square(int)x);当然更好的解决方案是在调用square函数前提供其原型。在C99中,调用square之前不提供声明或者定义是错误的。49第9章:函数数组型实际参数 当形式参数是一维数组时
展开阅读全文