大学C程序设计方案教程.ppt_第1页
大学C程序设计方案教程.ppt_第2页
大学C程序设计方案教程.ppt_第3页
大学C程序设计方案教程.ppt_第4页
大学C程序设计方案教程.ppt_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

大学C+程序设计教程,西安交通大学 计算机教学实验中心 ,1/33,第8章 函数和指针,C+语言的模块设计离不开函数,函数设计更离不开参数。 掌握函数设计和调用的正确方法,是程序设计的基本功。 正确设计函数原型和参数类型,不仅能保证函数的正确性,而且能提高程序设计的效率。 介绍函数调用、递归调用以及函数调用中的参数替换和返回值等问题之外,还将结合软件编程技术的发展,讨论函数指针、内联函数、函数重载等。 理解指针和函数的几种关系,2/33,授课内容,8.1 递归函数 8.2 函数重载 8.3 指针和函数 8.4 带参数的main()函数 8.5 内联函数 8.6 不使用参数的函数 8.7 void和const类型的指针,3/33,一、递归函数,函数调用,一般是一个函数调用另外一个函数。此外,函数还可以自己调用自己,这种调用叫做函数的递归调用。 递归调用有两种方式,一种是直接调用其本身,另一种是通过其他函数间接地调用。,4/33,一个问题是否可以转换为递归来处理必须满足以下条件: (1)必须包含一种或多种非递归的基本形式; (2)一般形式必须能最终转换到基本形式; (3)由基本形式来结束递归。 递归调用在堆栈中临时占据的存储区域是较多的,在实际运行时,递归调用的时间效率较差。,5/33,例8-1 采用递归算法求n!,算 法: 由阶乘的概念可以写出其递归定义: 0! = 1 n! = n*(n-1)!,6/33,Example 8-1:用递归方法求n!,/ 函数fac():求阶乘的递归函数 int fac(int n) if(n0) / 不能求负数的阶乘 return 1; else if(n=0) / 0的阶乘为1 return 1; else return n*fac(n-1); / n!为(n-1)!乘以n ,7/33,例8-2 梵塔(hanoi塔)问题,算 法: 如果只有1片金片时,只要直接将金片从A针移到C针上即可; 当n1时,就需要借助另外一个针来移动。将n片金片由A移到C上可以分解为以下几个步骤: (1) 将A上的n1片金片借助C针移到B针上; (2) 把A针上剩下的一片金片由A针移到C针上; (3) 最后将剩下的n1个金片借助A针由B针移到C针上。 步骤(1)和(3)与整个任务类似,但涉及的金片只有n1个了。这是一个典型递归算法。,8/33,9/33,例8-2 梵塔(hanoi塔)问题,#include const int N=3; /考察当金片数为3个时的情况 void move(char from, char to) / 函数move():将金片由一根针移到另一根针上 cout “From “ from “ to “ to endl; ,10/33,void hanoi(int n, int p1, int p2, int p3) if(n=1) move(p1, p3); else hanoi(n-1, p1, p3, p2); move(p1, p3); hanoi(n-1, p2, p1, p3); int main() hanoi(N, A, B, C); return 0; ,11/33,二、函数重载,函数重载使一个函数名具有多种功能,即具有“多种形态”,称这种形态为多态性。 函数重载: 一组参数和返回值不同的函数共用一个函数名。 例如求绝对值函数,对应不同的参数类型,可以定义如下几个重载函数: int abs(int); double fabs(double); long labs(1ong);,12/33,当某个函数中调用到重载函数时,编译器会根据实参的类型去对应地调用相应的函数。匹配过程按如下步骤进行: (1)如果有严格匹配的函数,就调用该函数; (2)参数内部转换后如果匹配,调用该函数; (3)通过用户定义的转换寻求匹配。,13/33,例8-3 重载绝对值函数,#include int abs(int x) return x=0?x:-x; double abs(double x) return x=0?x:-x; long abs(long x) return x=0?x:-x; ,void main() int x1 = 1; double x2 = 2.5; long x3 = 3L; cout “|x1| = “ abs(x1) endl; cout “|x2| = “ abs(x2) endl; cout “|x3| = “ abs(x3) endl; ,14/33,8.3 指针和函数,8.3.1 指针作为函数的参数 8.3.2 返回指针的函数 8.3.3 指向函数的指针,15/33,8.3.1 指针作为函数的参数,函数的参数不仅可以是基本数据类型的变量、对象名、数组名或函数名,而且可以是指针。 例7.1例7.3都使用了这一方法。 通过使实参与形参指针指向共同的内存空间,达到了参数双向传递的目的。,16/33,8.3.2 返回指针的函数,函数返回值类型不仅可以是int、double之类的简单类型,也可以将一个地址 (如变量、数组和函数的地址,指针变量的值等)作为函数的返回值。 在说明返回值为地址的函数时,要使用指针类型说明符,例如: char *strchr(char *string, int c); char *strstr(char *string1, char *string2);,17/33,例8-4 将月份数值转换为相应的英文名称,char *month_name(int n) static char *month= “Illegal month“, “January“, “February“, “March“, “April“, “May“, “June“, “July“, “August“, “September“,“October“, “November“, “December“ ; return (n=1 ,18/33,8.3.3 指向函数的指针,首地址是函数的入口地址。主函数在调用子函数时,就是让程序转移到函数的入口地址开始执行。 指向函数的指针:就是指针的值为该函数的入口地址。,19/33,指向函数的指针变量的说明格式为: (*)(); 例如: int(*p)(); / p为指向返回值为整型的函数的指针 float(*q)(float,int); / q为指向返回值为浮点型函数的指针,20/33,例8-5 通用数值积分函数,double integral(double a, double b, double (*fun)(double), int n) double h = (b-a)/n; double sum = (*fun)(a)+(*fun)(b)/2; int i; for(i=1; in; i+) sum += (*fun)(a+i*h); sum *= h; return sum; ,/,21/33,调试函数 integral() 的主函数,double func(double x) return sin(x)+x; void main() double sum; sum = integral(0.0, 1.0, func, 1000); cout(“The Integral of sin(x)+x, 0, 1 is ” sum; ,22/33,8.4 带参数的main()函数,函数原型为: int main(int argc, char *argv) 第一个整型参数指明在以命令行方式执行本程序时所带的参数个数(包括程序名本身,故argc的值至少为1); 第二个参数为一个字符型指针数组(其中第1个下标变量argv0指向本程序名,接下来的下标变量argv1,argv2.等分别指向命令行传递给程序的各个参数),用来存放命令行中命令字及各个参数的字符串。,23/33,例8-6 带参数的main函数,#include int main(int a, char *ar) if(a!=2) cout“endl; return 1; cout“Hello, “ar1“. Welcome to the world of C+ !“endl; return 0;,24/33,自学内容,8.5 内联函数 8.6 不使用参数的函数 8.7 void和const类型的指针,25/33,8.5 内联函数,内联函数机制通过将函数体的代码直接插入到函数调用处来节省调用函数的时间开销, 内联函数实际上是一种用空间换时间的方案,其目的是为了提高函数的执行效率。 要定义一个内联函数,只需在定义函数时将该函数用关键字inline修饰即可,26/33,8.6 不使用参数的函数,void用于函数的参数表, 是明确说明该函数不使用参数; void说明函数的返回值则是说明该函数不提供任何返回值。,27/33,8.7 void和const类型的指针,指向void类型的指针是通用型的指针, 可以指向任何类型的变量。 用关键字const修饰一个指针时,根据其位置的不同有不同的含义。例如: const char *ptr = “Point to constant string”; /定义了一个指向常数字符串的指针 char *const qtr = “A constant pointer”; /定义了一个常指针。 修饰符const多用于修饰函数的指针或引用参数,以防止在编程中无意识地改变其值。,28/33,程序设计举例,例8-8 改善模拟梵塔问题的递归程序,打印更多的信息。 例8-9 采用递归算法寻找一个整型数组中的最大元素。 例8-10 重载上例的求最大元素的函数。 例8-11 编写一个用于在字符串中查找某字符的函数。 例8-12 编写一个用于三个整型变量排序的程序。,29/33,实例编程-五子棋,算法 棋局数组 数组内部相干元素的关系,30/33,小 结,递归函数是直接或间接地调用了自身的函数。 每个递归函数必须包含一种或多种非递归的基本形式,一般形式必须能最终转换到基本形式,而基本形式可以结束递归。 函数重载是指一组参数和返回值不同的函数共用一个函数名,编译器会根据函数参数的不同(包括类型、个数和顺序)来确定应该调用哪一个函数。,31/33,重载函数之间必须在参数的类型或个数方面有所不同。只有返回值类型不同的几个函数不能重载。 指针和函数的关系可以有以下几种:指针作为函数的参数,指针作为函数的返回值,指向函数的指针。 带参数的main()函数原型:int main(int argc, char *argv),32/33,习 题,1用指针重新编写例4-5的冒泡排序程序。 2编写程序,将某一个输入的位数不确定的正整数按照标准的三位分节格式输出,例如,当用户输入82668634时,程序应该输出82,668,634。 3编写程序,把10个整数1、2、10赋予某个int型数组,然后用int型指针输出该数组元素的值。 4用指针编写一个程序,当输入一个字符串后,要求不仅能够统计其中字符的个数,还能分别

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论