230 likes | 417 Views
C 语言程序设计. 主讲教师:王英. 项目七:函数及指针 —— 统计学生成绩. 任务一: 使用函数统计学生成绩. 任务二: 使用指针统计学生成绩. 任务三:使用指针简化程序. 任务一:使用函数统计学生成绩. 当制作复杂的程序时,如何提高层次结构的清晰性,以便于程序的编写、阅读、调试。 函数 (functions) 概述 C 程序是由函数组成的 。 函数分为主函数、库函数、用户自定义函数三种。程序的执行由主函数开始,然后调用其它函数,最终返回主函数结束。 函数的定义 ( Function definitions ) 定义的一般格式如下:
E N D
C语言程序设计 主讲教师:王英
项目七:函数及指针——统计学生成绩 任务一:使用函数统计学生成绩 任务二:使用指针统计学生成绩 任务三:使用指针简化程序 Company Logo
任务一:使用函数统计学生成绩 当制作复杂的程序时,如何提高层次结构的清晰性,以便于程序的编写、阅读、调试。 函数(functions)概述 • C程序是由函数组成的。 • 函数分为主函数、库函数、用户自定义函数三种。程序的执行由主函数开始,然后调用其它函数,最终返回主函数结束。 • 函数的定义(Function definitions ) 定义的一般格式如下: 类型名 函数名([类型名 形式参数1 , 类型名 形式参数2 , …]) { 说明部分 /* 函数体 */ 语句部分 } formal parameter Company Logo
任务一:使用函数统计学生成绩 • 函数的返回值(the returned values 0f functions) 通过函数体内的return语句实现。return语句的格式如下: return 表达式 ; 或 return (表达式) ; 如果没有返回值,格式中的左、右圆括号可以省略,即写为: return ; Company Logo
任务一:使用函数统计学生成绩 • 函数的调用(function call) 函数调用的一般形式为: 函数名([实参表]) ; • 如果是调用无参函数,则[实参表]可以没有,但括号不能省略。 • 如果实参表列包含多个实参,则各实参间用逗号隔开。实参与形参的个数应相等,类型应一致。 • 实参与形参按顺序对应,一一传递数据。 actual parameter Company Logo
任务一:使用函数统计学生成绩 1 2 3 函数参数 被调函数作为另一个函数的参数时的调用,而另一个函数则是被调函数的主调函数。 例如:m=fun(2,max(3,4)) 函数表达式 在被调函数中,必须有一个函数返回值,返回主调函数以参加表达式的运算。 例如:max=fun(2,3) 函数语句 把被调函数作为一个独立的语句直接出现在主调函数中。 例如:fun(2,3) • 函数调用的方式有三种: 主讲人:王英
任务一:使用函数统计学生成绩 • 注意: • 被调函数必须是已存在的函数,可以是自定义函数,也可以是库函数。 • 在主调函数中,要对被调函数先做声明,放在源文件的开头,则该声明对整个源文件都有效,在调用函数定义的内部,则该声明仅对该调用函数有效。。 • 调函数的返回值为int类型,可省略。 • 调用和被调用函数的定义是在同一源文件中,应该先说明或定义被调用函数。 • 在函数调用中,有下面几种情况可以省略声明: • 如果调用和被调用函数是在同一个源文件中,而且被调用函数的定义是在调用函数之前。 • 函数的返回值是整型。 • 所有被调用函数的声明都是在源文件开头。 Company Logo
任务一:使用函数统计学生成绩 函数的嵌套调用(function nested calling) C语言中的函数定义是互相独立的,函数和函数之间没有从属关系,一个函数既可以被其它函数调用,同时它也可以调用别的函数,这就是函数的嵌套调用。 调用 调用 调用 main printf fun1 fun2 返回 结束 返回 int fun2(int a,int b) { return (a*b); } Int fun1(int a,int b) { int c; a+=a; b+=b; c=fun2(a,b); return c; } main() { int x=3,y=5; printf(“%d\n”,fun1(x,y)); } 函数调用过程图 想一想:函数是否可以调用自己? Company Logo www.themegallery.com
任务一:使用函数统计学生成绩 函数的递归调用(function Recursively calling) 函数的递归调用有两种形式: 直接递归调用,即一个函数可直接调用该函数本身。 间接递归调用,即一个函数可间接地调用该函数本身。 fun1(int x) { if(x==1) return 1; else return x*fun2(x-1) ;} fun2(int y) { int z; z=fun1(y); return z;} fun(t) { if (t==1) {s=1;} s= t*fun(t-1) } Company Logo www.themegallery.com
任务一:使用函数统计学生成绩 • 函数调用时参数间的传递(transfer) 变量、常量、数组元素作为函数参数 将实参的值复制到形参相应的存储单元中,即形参和实参分别占用不同存储单元,这种传递方式称为“值传递”。值传递的特点是单向传递。 数组名作为函数参数 把实参数组的首地址传给形参数组,这个两个数组共用一段存储单元,即实参数组名和形参数组名共同指向数组的第一个元素。形参的变化直接影响实参。 主讲人:王英
任务一:使用函数统计学生成绩 知识扩展 局部变量和全局变量 局部变量 在一个函数内定义的变量称为内部变量,它只在本函数内有效,而在其它函数内不能使用,故这些变量又称为局部变量。 全局变量 在函数外部定义的变量称为外部变量,外部变量是全局变量。全局变量的作用范围为:从定义全局变量位置开始到源程序结束。 全局变量可以在其作用范围内由其它函数所共用。 Company Logo www.themegallery.com
任务一:使用函数统计学生成绩 • 静态存储变量和动态存储变量 • 静态变量:在程序运行期间分配固定的存储空间的变量。静态存储变量的定义格式为: static 数据类型名 变量名[=初始化常数表达式] 例如:static int a=3; 注意:静态变量在程序的执行过程中一直存在,直到程序终止。 • 动态变量:在程序运行期间根据需要进行动态的分配存储变量,它是在程序执行的某一时刻被动态建立,在另一时刻被动态撤消的一种变量。 动态存储变量有两种:自动(auto)变量和寄存器(register)变量。
任务一:使用函数统计学生成绩 • 自动变量(auto) [auto] 类型名 变量名[=初始表达式] ,… auto为自动变量存储类别标识符,[auto]可省略,系统默认为auto。以前函数中所定义的变量大都是auto变量。 • 寄存器变量(regist) register 类型名变量名 是指将变量的值保留在CPU(中央处理器)的寄存器内,它不占用内存单元。程序运行时,可以直接访问寄存器内的数据,其速度比访问内存的数据快得多。
任务一:使用函数统计学生成绩 使用函数编写统计学生成绩的程序如下: fun(g[][],s[]) { for(int i=0;i<N;i++) { for(int j=0;j<M;j++) sum[i]+= g[i][j]; } } main() { int g[N][M],s[M]; fun(g,s); for(int i=0;i<M;i++) printf(“%d”,s[i]); }
任务二:使用指针统计学生成绩 • 指针(pointer)的基本概念 指针就是地址,是一种数据类型。 • 指针变量的定义: 一般格式为: 类型名 * 指针变量 例如: int i , j , * p1 , *p2 ; • 一个指向指针的指针变量的定义: int **p; 注:p中存放的是指针变量的地址;*p中存放的是变量的地址
任务二:使用指针统计学生成绩 • 指针变量的引用 可以通过指针运算符“*”引用指针变量,指针运算符可以理解为“指向”的含义。 例如:int a,*p=&a; a可用*p表示 • 指针变量的赋值 int i=3,*p=&i; 或者 int i=3,*p; p=&i; • 指针变量作为函数参数 函数参数也可以是指针变量,其作用是将变量的地址传到另一函数中去。
任务二:使用指针统计学生成绩 指针与一维数组 使用指针指向一维数组 int a[5],*p=a,*q=&a[2]; 指针的运算 算术运算 p++; s=*p++; s=*++p; 关系运算 int m=p<q *的优先级高于++,将a[0]的值 加1赋值给s。 *和++都是右结合性,将a[1]的值赋值给s。 m=1
任务二:使用指针统计学生成绩 数组元素的引用 下标形式 :p[2] 指针形式:*(p+2) 想一想:使用指针输入和输出数组元素? for(int i=0;i<5;i++) scanf(“%d”,&a[i]); for(int i=0;i<5;i++) printf(“%d”, a[i]); for(int i=0;i<5;i++) scanf(“%d”, p++); for(int i=0;i<5;i++) printf(“%d”, *p++);
任务二:使用指针统计学生成绩 指向数组的指针作为函数参数 void revert(int *q) { int * t=a+4,temp; for(;q<t;q++,t--) { temp=*q; *q=*t; *t=temp; } } main() { int a[5]={1,2,3,4,5},*p=a; revert(p); for(int i=0;i<5;i++) printf(“%d”,*p++); }
任务二:使用指针统计学生成绩 指针与字符串 通过指针变量引用字符串 字符串指针作为函数参数 main() { char *s=“Hello World”; s+=7; printf(“%s”,s); }
任务二:使用指针统计学生成绩 使用指针统计学生成绩代码如下: fun(int g[][],int s[]) { int *p=s; for(int i=0;i<N;i++) { for(int j=0;j<M;j++) *p+= g[i][j]; p++; } } main() { int g[N][M],s[M]; fun(g,s); for(int i=0;i<M;i++) printf(“%d”,s[i]); }
任务二:使用指针简化程序 使用指针简化程序代码如下: fun(int **q, int *p) { for(int i=0;i<N;i++,p++) { for(int j=0;j<M;j++,q++) *p+=**q; } } main() { int g[N][M],s[M]; fun(g,s); for(int i=0;i<M;i++) printf(“%d”,s[i]); }
Thank You ! Click to edit company slogan .