C语言程序设计 清华大学出版社 5(函数)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统 17/44 Lifang 2013
例6-9:计算一组整数中偶数的个数,偶数判断用函数实现 P101 #include<stdio.h> void main() { int a[10]={4,7,9,1,54,67,88,2,21,3}; int i,s=0; float even_num(int a[10]); for(i=0;i<10;i++) s+=even_num (a[i]); printf("%d",s); } float even_num(int n) /*数组作函数的参数*/ { if(n%2==0) return 1; else return 0; }
操作系统 16/44 Lifang 2013
6.4 数组作函数的参数 P103
6.4.1 一维数组作参数 例6-8:求10名学生的平均成绩
#include<stdio.h> void main() { int a[10]={4,7,9,1,54,67,88,2,21,3}; float ave; float average(int a[10]); /*函数声明*/ ave=average(a); /*将数组a传递给average*/ printf("%7.2f",ave); } float average(int m[10]) /*数组作函数的参数*/ { int i,sum=0; for(i=0;i<10;i++) sum+=m[i]; return sum/10.0; }
返回6(3*2)
返回2(2*1)
操作系统
12/44
Lifang 2013
递归调用的实质就是将原来的问题分解为新的问题,而解决新问题 时又用到了原有问题的解法。 按照这一原则分解下去,每次出现的新问题都是原有问题的简化的 子问题,而最终分解出来的问题,是一个已知解的问题。这就是有 限的递归调用。 只有有限的递归调用才是有意义的,无限的递回调用永远得不到解, 没有实际意义。
void Sort() {… }
排序函数调用(冒泡…);
sort();
对一些常用的功能,希望象使用scanf(),printf()那样调用现成的模块 来实现,从而使得程序结构更清晰、避免代码重复。——可以自己 定义函数
操作系统 2/44 Lifang 2013
第
6章
函 数
引例
函数的定义和调用
递归函数 数组与函数 *程序的多文件组织 作用域及存储类型
操作系统 8/44 Lifang 2013
#include<stdio.h> int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; } main() { int n,res; scanf("%d",&n); res=JC(n); printf("%d",res); }
操作系统
19/44
Lifang 2013
6.4.3 二维数组作为函数参数
例6-11编写函数求已知二维矩阵主对角线上元素的最大值 #include<stdio.h> void main() { int a[3][3]={1,2,3,4,5,6,7,8,9}; int main_max(int s[3][3]); int res; res=main_max(a); printf("主对角线元素最大值为%d\n",res); } int main_max(int s[3][3]) /*二维数组作函数的参数*/ { int i; int m=s[0][0]; for(i=1;i<3;i++) if(s[i][i]>m) m=s[i][i]; return m; }
递归三要素:
–递归形式 :FN(n) –递归规则:n*(n-1)! –递归终结条件:n=1
int FN( int n ) { if( n<=1 ) return 1; return n*FN( n-1 ); }
操作系统
13/44
Lifang 2013
汉诺塔问题
假设三个塔,第一个塔上有从小到大堆积的一叠金 属片,一次从一个塔搬运一片到另一个塔,只能从塔顶 搬运,不允许大的金属片压在小的金属片上,求解将金 属片全部搬运到第三个塔上的过程及搬运次数
*函数的存储类型
操作系统
3/44
Lifang 2013
#include <stdio.h> main() { int a,b; int z; scanf(“%d%d”,&a,&b); if(a>b) z=a; else z=b; printf(“%d”,z); }
模块化程序设计 • 函数如何定义 • 函数如何使用 • 调用函数时,数据如何传递
操作系统
14/44
Lifang 2013
递归解决
–递归形式:hannoi(int n,int a,int b,int c) n:片数 a:起点塔号,b:中间塔号,c:目标塔号 –递归规则: 先将n-1片搬运到中间塔上; 将最后一片搬运到目标塔上; 将n-1片从中间塔上搬运到目标塔上;
–递归终结条件: 当n=1时,直接搬运;
float y;
printf("input a inteager number:\n"); scanf("%d",&n);
if n<0 printf(“Data Error!”)
y=FN(n); printf("%d!=%ld\n",n,y);
getch();
}
操作系统 11/44 Lifang 2013
以计算3!为例,调用a = FN(3);
n为3
n为2
n为1
if( n<=1 ) return 1;
a = FN(3);
if( n<=1 ) return 1; return n * FN( n-1 );
if( n<=1 ) return 1; return n * FN( n-1 );
返回1
return n * FN( n-1 );
操作系统 10/44 Lifang 2013
6.3 函数的递归调用 P100
函数直接或间接地调用自身称为递归调用。
例:计算n! n!=n*(n-1)!
int FN( int n ) { if( n<=1 ) return 1; return n*FN( n-1 ); } main() { int n;
例
1)形参表语法:(类型 参数名,类型 参数名……) 形参表也可为空——无参函数 2)函数的返回类型可以省略,默认为int 函数的返回类型也可以是void型,表示无返回值 3)函数需要返回值时,用return语句。不需要时则不必使用。 return (表达式) 或 return 表达式 4)函数中可能有多条return语句,但只能有一条被执行.
函 数 的 调 用 流 程: 以 引 例 为 例:
例:编写函数,求一个数的阶乘,在主函数中调用该函数。
#include<stdio.h> int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; } main() { int n,res; scanf("%d",&n); res=JC(n); printf("%d",res); }
5) 函数不允许嵌套定义 ,函数之间是平行的。 操作系统
5/44
Lifang 2013
6.2.2 函数的调用 P96
•函数的调用语法 –函数名(实参,实参,……)
说明: 1)函数的调用在语法上相当于一个表达式,可构成表达式语句或作为另 一个表达式的操作数或作为流程控制语句的组成部分。 2)函数调用时的实参个数、类型应与函数定义中的形参个数、类型相吻合 ; 形参是函数定义时的参数,是变量; 仅在调用函数时,才为形参分配内存;调用结束后,形参所占内存马上释放 实参是函数调用时的参数,可以是常量、变量或表达式——是一个“值”。 3)调用的函数必须是已经定义了的函数。 4)函数的调用是可以嵌套的; 两个名词:主调函数(主函数,子函数) 被调函数(子函数)
Lifang 2013
Baidu Nhomakorabea
6.2.1 函数的定义 P95
函数定义语法:
函数头 返回类型 函数名(形参表) 函 数 体 { 说明语句; 执行语句…;
return (表达式)
}
int max(int x,int y) { int z; if(x>y) z=x; else z=y; retutn(z); }
9/44 Lifang 2013
操作系统
6.2.3 函数的存在性说明(函数声明) P98
#include<stdio.h> main() 返回类型 函数名(形参表); { int n,res; int JC(int x); int JC(int ); scanf("%d",&n); res=JC(n); printf("%d",res); 说明: } 1) 存在性说明也称为函数原型(prototype), int JC(int x) 系统利用函数原型对函数的合法性进行检查。 { int i, s=1; for(i=1;i<=x;i++) Error: Function…should have a prototype! s*=i; 2) 库函数的原型在.h文件中 return s; 3) 常见库函数的原型:见附录C P192 } 看到函数原型就应该知道函数的调用方法
main( ) 例 { int a,b,z; scanf(“%d%d”,&a,&b); z=max(a,b); printf(“%d”,z); }
操作系统
6/44
Lifang 2013
主调函数
被调函数 1
2
① 主调函数向被调函数传递: 在调用子函数时发生。以实参的方式向形参提供参数: ② 子函数向主调函数传递: 在被调函数即将执行完毕时发生。将结果return回主调函数 每次只能return 一个值。 操作系统 Lifang 2013 7/44
操作系统 18/44 Lifang 2013
6.4.2 函数间的参数传递
主调函数向被调函数传递时形参和实参可有两种类型:
1.可以是简单数据类型——“值传递”, res=JC(n); n为整型变量 s+=even_num (a[i]); a[i]为数组元素,也是整型变量 2.也可以是地址(数组,指针)——“地址传递”。 ave=average(a); a为数组名(即数组的首地址,代表数组)
函数调用
#include <stdio.h> main() { char c=„A‟; c+=32; printf(“%c”,c); … }
库函数 printf()
操作系统
1/44
Lifang 2013
#include <stdio.h> main() { 准备一组数据; 输出排序后的数据; }
操作系统
15/44
Lifang 2013
程序代码
#include <stdio.h> void hanoi( int n,int a,int b,int c ) { if( n==1 ){ printf( "Move chip%d from tower%d to tower%d\n",n,a,c ); } else { hanoi( n-1,a,c,b ); printf( "Move chip%d from tower%d to tower%d\n",n,a,c ); hanoi( n-1,b,a,c ); } } main() { int n; printf( “Hanoi Problem:\n Please input the number of diskes:" ); scanf( "%d",&n ); hanoi( n,1,2,3 ); return 0; }
#include<stdio.h> main() { int n,res; int JC(int x); scanf("%d",&n); res=JC(n); printf("%d",res); } int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; }
操作系统 4/44
6.1 引例 P94
#include<stdio.h> int max(int x,int y) { int z; if(x>y) z=x; else z=y; retutn(z); } main() { int a,b,z; scanf(“%d%d”,&a,&b); z=max(a,b); printf(“%d”,z); }
例6-9:计算一组整数中偶数的个数,偶数判断用函数实现 P101 #include<stdio.h> void main() { int a[10]={4,7,9,1,54,67,88,2,21,3}; int i,s=0; float even_num(int a[10]); for(i=0;i<10;i++) s+=even_num (a[i]); printf("%d",s); } float even_num(int n) /*数组作函数的参数*/ { if(n%2==0) return 1; else return 0; }
操作系统 16/44 Lifang 2013
6.4 数组作函数的参数 P103
6.4.1 一维数组作参数 例6-8:求10名学生的平均成绩
#include<stdio.h> void main() { int a[10]={4,7,9,1,54,67,88,2,21,3}; float ave; float average(int a[10]); /*函数声明*/ ave=average(a); /*将数组a传递给average*/ printf("%7.2f",ave); } float average(int m[10]) /*数组作函数的参数*/ { int i,sum=0; for(i=0;i<10;i++) sum+=m[i]; return sum/10.0; }
返回6(3*2)
返回2(2*1)
操作系统
12/44
Lifang 2013
递归调用的实质就是将原来的问题分解为新的问题,而解决新问题 时又用到了原有问题的解法。 按照这一原则分解下去,每次出现的新问题都是原有问题的简化的 子问题,而最终分解出来的问题,是一个已知解的问题。这就是有 限的递归调用。 只有有限的递归调用才是有意义的,无限的递回调用永远得不到解, 没有实际意义。
void Sort() {… }
排序函数调用(冒泡…);
sort();
对一些常用的功能,希望象使用scanf(),printf()那样调用现成的模块 来实现,从而使得程序结构更清晰、避免代码重复。——可以自己 定义函数
操作系统 2/44 Lifang 2013
第
6章
函 数
引例
函数的定义和调用
递归函数 数组与函数 *程序的多文件组织 作用域及存储类型
操作系统 8/44 Lifang 2013
#include<stdio.h> int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; } main() { int n,res; scanf("%d",&n); res=JC(n); printf("%d",res); }
操作系统
19/44
Lifang 2013
6.4.3 二维数组作为函数参数
例6-11编写函数求已知二维矩阵主对角线上元素的最大值 #include<stdio.h> void main() { int a[3][3]={1,2,3,4,5,6,7,8,9}; int main_max(int s[3][3]); int res; res=main_max(a); printf("主对角线元素最大值为%d\n",res); } int main_max(int s[3][3]) /*二维数组作函数的参数*/ { int i; int m=s[0][0]; for(i=1;i<3;i++) if(s[i][i]>m) m=s[i][i]; return m; }
递归三要素:
–递归形式 :FN(n) –递归规则:n*(n-1)! –递归终结条件:n=1
int FN( int n ) { if( n<=1 ) return 1; return n*FN( n-1 ); }
操作系统
13/44
Lifang 2013
汉诺塔问题
假设三个塔,第一个塔上有从小到大堆积的一叠金 属片,一次从一个塔搬运一片到另一个塔,只能从塔顶 搬运,不允许大的金属片压在小的金属片上,求解将金 属片全部搬运到第三个塔上的过程及搬运次数
*函数的存储类型
操作系统
3/44
Lifang 2013
#include <stdio.h> main() { int a,b; int z; scanf(“%d%d”,&a,&b); if(a>b) z=a; else z=b; printf(“%d”,z); }
模块化程序设计 • 函数如何定义 • 函数如何使用 • 调用函数时,数据如何传递
操作系统
14/44
Lifang 2013
递归解决
–递归形式:hannoi(int n,int a,int b,int c) n:片数 a:起点塔号,b:中间塔号,c:目标塔号 –递归规则: 先将n-1片搬运到中间塔上; 将最后一片搬运到目标塔上; 将n-1片从中间塔上搬运到目标塔上;
–递归终结条件: 当n=1时,直接搬运;
float y;
printf("input a inteager number:\n"); scanf("%d",&n);
if n<0 printf(“Data Error!”)
y=FN(n); printf("%d!=%ld\n",n,y);
getch();
}
操作系统 11/44 Lifang 2013
以计算3!为例,调用a = FN(3);
n为3
n为2
n为1
if( n<=1 ) return 1;
a = FN(3);
if( n<=1 ) return 1; return n * FN( n-1 );
if( n<=1 ) return 1; return n * FN( n-1 );
返回1
return n * FN( n-1 );
操作系统 10/44 Lifang 2013
6.3 函数的递归调用 P100
函数直接或间接地调用自身称为递归调用。
例:计算n! n!=n*(n-1)!
int FN( int n ) { if( n<=1 ) return 1; return n*FN( n-1 ); } main() { int n;
例
1)形参表语法:(类型 参数名,类型 参数名……) 形参表也可为空——无参函数 2)函数的返回类型可以省略,默认为int 函数的返回类型也可以是void型,表示无返回值 3)函数需要返回值时,用return语句。不需要时则不必使用。 return (表达式) 或 return 表达式 4)函数中可能有多条return语句,但只能有一条被执行.
函 数 的 调 用 流 程: 以 引 例 为 例:
例:编写函数,求一个数的阶乘,在主函数中调用该函数。
#include<stdio.h> int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; } main() { int n,res; scanf("%d",&n); res=JC(n); printf("%d",res); }
5) 函数不允许嵌套定义 ,函数之间是平行的。 操作系统
5/44
Lifang 2013
6.2.2 函数的调用 P96
•函数的调用语法 –函数名(实参,实参,……)
说明: 1)函数的调用在语法上相当于一个表达式,可构成表达式语句或作为另 一个表达式的操作数或作为流程控制语句的组成部分。 2)函数调用时的实参个数、类型应与函数定义中的形参个数、类型相吻合 ; 形参是函数定义时的参数,是变量; 仅在调用函数时,才为形参分配内存;调用结束后,形参所占内存马上释放 实参是函数调用时的参数,可以是常量、变量或表达式——是一个“值”。 3)调用的函数必须是已经定义了的函数。 4)函数的调用是可以嵌套的; 两个名词:主调函数(主函数,子函数) 被调函数(子函数)
Lifang 2013
Baidu Nhomakorabea
6.2.1 函数的定义 P95
函数定义语法:
函数头 返回类型 函数名(形参表) 函 数 体 { 说明语句; 执行语句…;
return (表达式)
}
int max(int x,int y) { int z; if(x>y) z=x; else z=y; retutn(z); }
9/44 Lifang 2013
操作系统
6.2.3 函数的存在性说明(函数声明) P98
#include<stdio.h> main() 返回类型 函数名(形参表); { int n,res; int JC(int x); int JC(int ); scanf("%d",&n); res=JC(n); printf("%d",res); 说明: } 1) 存在性说明也称为函数原型(prototype), int JC(int x) 系统利用函数原型对函数的合法性进行检查。 { int i, s=1; for(i=1;i<=x;i++) Error: Function…should have a prototype! s*=i; 2) 库函数的原型在.h文件中 return s; 3) 常见库函数的原型:见附录C P192 } 看到函数原型就应该知道函数的调用方法
main( ) 例 { int a,b,z; scanf(“%d%d”,&a,&b); z=max(a,b); printf(“%d”,z); }
操作系统
6/44
Lifang 2013
主调函数
被调函数 1
2
① 主调函数向被调函数传递: 在调用子函数时发生。以实参的方式向形参提供参数: ② 子函数向主调函数传递: 在被调函数即将执行完毕时发生。将结果return回主调函数 每次只能return 一个值。 操作系统 Lifang 2013 7/44
操作系统 18/44 Lifang 2013
6.4.2 函数间的参数传递
主调函数向被调函数传递时形参和实参可有两种类型:
1.可以是简单数据类型——“值传递”, res=JC(n); n为整型变量 s+=even_num (a[i]); a[i]为数组元素,也是整型变量 2.也可以是地址(数组,指针)——“地址传递”。 ave=average(a); a为数组名(即数组的首地址,代表数组)
函数调用
#include <stdio.h> main() { char c=„A‟; c+=32; printf(“%c”,c); … }
库函数 printf()
操作系统
1/44
Lifang 2013
#include <stdio.h> main() { 准备一组数据; 输出排序后的数据; }
操作系统
15/44
Lifang 2013
程序代码
#include <stdio.h> void hanoi( int n,int a,int b,int c ) { if( n==1 ){ printf( "Move chip%d from tower%d to tower%d\n",n,a,c ); } else { hanoi( n-1,a,c,b ); printf( "Move chip%d from tower%d to tower%d\n",n,a,c ); hanoi( n-1,b,a,c ); } } main() { int n; printf( “Hanoi Problem:\n Please input the number of diskes:" ); scanf( "%d",&n ); hanoi( n,1,2,3 ); return 0; }
#include<stdio.h> main() { int n,res; int JC(int x); scanf("%d",&n); res=JC(n); printf("%d",res); } int JC(int x) { int i, s=1; for(i=1;i<=x;i++) s*=i; return s; }
操作系统 4/44
6.1 引例 P94
#include<stdio.h> int max(int x,int y) { int z; if(x>y) z=x; else z=y; retutn(z); } main() { int a,b,z; scanf(“%d%d”,&a,&b); z=max(a,b); printf(“%d”,z); }