📄 函数1.txt
字号:
主要内容
1.函数的定义和调用
2.变量的存储类型
3.函数的递归调用
4.内联函数
5.重载函数
6.默认参数的函数
第八讲函数
刘志敏
北京大学信息科学技术学院
liuzm@pku.edu.cn
3
函数的层次关系
§程序:完成一定功能的指令集合
§例如:输入一整数,判断是否为素数
§输入数据
§判断是否为素数
§显示结果
§根据功能划分成模块(函数),降低程序复
杂度
§库函数
§自定义函数
main( )
输入数据判断素数显示结果..
将验证素数的程序改为函数形式
#include <iostream>
#include <cmath>
using namespace std;
bool checkprime( int ); // 函数声明
void main() // 主函数
{ int a=0; // 定义整型变量,初始化为
0
cout << "请输入一个整数:
a=";
cin>> a; // 键盘输入一个整数
if ( checkprime(a) ) //函数调用
cout << a << "是素数" << endl;
else
cout << a << "不是素数" << endl;
} 4
定义函数
checkprime
形式参数和实在参数
//验证素数
bool checkprime( intb)
形式参数
{
int k=0;
for (k=2; k<=sqrt((double)b); k++) // 循环
{
if (b%k == 0)
{
return 0; //函数返回
}
}
}
return 1; // b不能被
k整除,则返回
1
5
bool checkprime( int b ); //定义
b 是形式参数
q形式参数特点:
|未被调用不占内存单元;
|被调用后系统为其分配内存单元;
|调用结束释放内存单元;
|作用域限定在函数内,属于局部变量。
7
函数调用
被调用函数嵌套在if 语句中,a 是
实在参数
if ( checkPrime ( a ) ) 函数调用
checkPrime ( b ) 函数
形式参数
8
函数调用(续)
q实在参数是一个具有确定值的表达式,
调用函数时,要将实在参数赋给形式参数
调用时
17 17
实在参数a 形式参数b
函数调用
被调用函数嵌套在if 语句中,a 是
实在参数
if ( checkPrime ( a ) ) 函数调用
checkPrime ( b ) 函数
形式参数
8
函数调用(续)
q实在参数是一个具有确定值的表达式,
调用函数时,要将实在参数赋给形式参数
调用时
17 17
实在参数a 形式参数b
9
输入a 函数
if (checkPrime(a))
checkPrime( b )
执行if 语句for: i=2,3 …
==1 ==0
b%i==0 !=0
输出输出return 0 return 1
a是质数a不是质数返回
函数调用(续)
函数调用(续)
int main()
{
int a=0; cout << "请输入一个整数:
a=";
cin >> a;
if ( checkprime(a) )
bool checkprime(int b)
{int k=0;
for (k=2; k<=sqrt((double)b); k++)
{ if (b%k == 0) return 0; }
return 1; }
cout << a << "是素数" << endl;
else
cout << a << "不是素数" << endl; }
函数定义
函数声明
q格式:函数返回值的类型函数名(类型名形参
1,
类型名形参
2,...)
{函数内局部变量说明
函数执行部分
return 语句;
}
§函数返回值的类型:无返回值的,为
void;不规定
类型的,默认为整型
§形式参数表:
§函数体:函数的局部变量,只允许在本函数内使用
§函数返回:
return 语句:
return(表达式);函数
返回到调用处
11
q格式:函数返回值的类型函数名(类型名
形参1,类型名形参2,...);
|功能:说明函数的形式
|位于程序的前部,告知系统有自定义的函
数
|只有当调用函数位于函数定义之后时,才
可以不进行函数声明
函数调用
函数调用(续)
q格式:函数名(实在参数表);
|有返回值的函数可在表达式中用;
|无返回值的,作为独立的语句出现
§要在程序前部说明函数的原型
§系统提供的函数,其函数原型在头文件中
§被调用函数与调用函数在程序中先后顺序无关
§被调用函数与调用函数可位于不同的源程序文件
(演示)
13
q主函数和其它函数均可调用函数(main函数
除外,函数可递归调用)
q参数传递仅是数值传递,形式参数中数据改
变不影响实在参数中的数据,因形式参数与
实在参数占用不同存储单元
15
参数传递仅是数值传递
例:调用函数swap (a,b),交换a,b的值
void swap(int a,int b);
void main()
{ int a=2,b=3;
cout <<a<<b;
swap(a,b);
cout <<"after swap"<<a<<b<<endl;
}
void swap(int x,int y)
{ int t=x; x=y; y=t;
}
结果2 3 after swap 2 3
q函数调用的结果不影响实参,因形参与实参占不同的内
存空间
2
a
3
b
2
x
3
y
main swap
nk
问题
问题问题:
::编程求解
编程求解编程求解.x
1x=
q分析:
1、定义函数
m
sop(m,k) =. pow(i,k )
i=1
|i=1,2,…… ,m
|pow(i,k)
|求和
|返回和值
2、主程序输入n和k,调用sop(n,k),输出结
果
参考程序
参考程序
#include <iostream>
#include <cmath>
using namespace std;
int sop(int m, int n); // 声明函数SOP
void main()
{
int n, k;
cout<<“input n and k:”;
cin>>n>>k;
cout<< "Sum of " << k
<< "from th powers of integers 1 to "
<< n<< " is "<< sop(n,k)<< endl;
}
17
//函数功能:计算1,2,...,m的l次幂的和
int sop(int m, int n) //m,n为形参
{ int i, sum=0; // 初始化累加器
for(i=1; i<=m; i++ )
sum=sum+pow ( i, n ); // 累加
return sum; // 返回值
}
q注:函数调用,形参与实参是按位置结合
实参:n k
形参:m n
程序举例1
程序举例1(续)
例:先编写一函数
prime(int n)判断n为素数否,然
后,在
100以内检验Goodbach猜想的正确性
(即:一个大于
4的偶数可分解为
2个素数之和。)
q分析:
|函数prime(int n)判断n是否为素数
|主程序读入一个偶数m(>=4),产生
6到m之间的偶数
i,找到奇数
j,满足
j、(i-j)均为素数的条件
#include <cmath>
#include <iostream>
using namespace std;
bool prime(int n);
19
20void main (void)
{ int i , j , m ;
cout <<"输入偶数m\n";
cin >>m;
if(m<6||m%2) {
cout<<“输入错误”<<endl;
return; }
for(i=6; i<=m; i+=2){
for(j =3;j <=i/2; j+=2)
if(prime(j)&&prime(i-j))
{ cout<<i<<“= ”<<j<<"+“;
cout<<i-j<<endl;
break; }
}
}
bool prime(int n)
{ int j, k=sqrt(n);
for(j=2 ; j<k; j++)
if(n%j==0)
return (false) ;
return (true) ;
}
程序举例2
程序举例2(续)
例:寻找并输出11
~999之间的数m,满足m,m
2,m
3均
为回文数(回文数是指其各位数字左右对称的整数,
如121、1331等)
q分析:
|主程序产生11
~999之间的数m,
|函数bool
symm(int
n)判断n是否为回文数
21
#include <iostream>
using namespace std;
bool symm(int n); //声明函数symm
void main(void)
{ int m;
for(m=11; m<1000; m++)
if (symm(m)&&symm(m*m)&&symm(m*m*m))
{
cout <<"m="<<m<<"\tm*m="<<m*m;
cout <<"\tm*m*m="<<m*m*m<<endl;
}
} 22
函数定义
bool symm(int n) //函数定义
{ int i, m;
i=n ;
m=0 ;
while(i) {
m=m*10+i%10;
i=i/10 ;
} //数字倒序(123
— >321)
return ( m==n );
}
23
24
变量的存储类型
q程序的内存区域:
|代码区:存放程序代码
|全局数据区:全局数据、
静态数据
|堆区:程序的动态数据
|栈区:存放局部数据
q函数调用过程:
|建立被调函数的栈空间
|保护调用函数的运行状态
和返回地址
|传递参数
|将控制转交被调函数
代码区
全局数据区
堆区
栈区..
func(a);
调用函数..
......
被调函数..
func
变量的存储类型(续)
变量的存储类型(续)
q格式:存储类型数据类型变量名表
q存储类型:全局变量、局部变量、静态变量,外部
变量
|全局变量:在函数体外定义的普通变量,在程序
的每个函数中都可访问。作用范围从说明地方起
直到程序结束。
|局部变量:在函数体中定义的普通变量
2局部:在定义范围内,可以访问它们;在定义
范围外,不可访问
2动态:调用该函数时,系统才为函数分配存储
25
单元;退出该函数,则该存储单元由系统收回
|静态变量:static,在编译时分配存储单元,随
程序开始而开始
2局部静态变量:在定义函数内存取,前次调用
变量的结果可以代入下次调用的变量中
2静态全局变量:限制此变量仅能在本程序文件
中使用,不能延伸到其它文件
|外部变量:为使全局变量的作用域延伸到它其它
文件或定义位置前面的函数中,用
extern类型名变量名表
变量的存储类型:程序举例
程序举例
#include <iostream>
func(int a, int b)
using namespace std;
{ static int m=0, i=2;
func(int a, int b);
i+=m+1;
main()
m=i+a+b;
{
return m;
int k=4, m=1, p;
}
p=func(k,m);
cout <<p<<endl; 结果:
8
p=func(k,m);
17
cout <<p<<endl;
} 27
编写一程序显示Fibonacci数列的前n个数。
Fibonacci数列定义为:
f1=1 (n=1), f2=1 (n=2), fn=
fn-1+fn-2 (n>2)
#include <iostream>
using namespace std;
long fib(int x);
void main( )
{ int i,n;
cin >>n;
for(i=1;i<=n;i ++) {
cout << fib(i)<<"\t " ;
}
}
程序举例
//函数fib产生Fibonacci数列
f1=1 , f2=1 ,fn= fn-1+fn-2
long fib(int x)
{ static long f1=1,f2=1;
long f;
if(x>2) {
f=f1+f2;
f1=f2; f2=f;
return f;
}
else return 1;
}
29
程序举例
例:编写一个函数对数组中的数据按升序排
序;另一个函数在排序的数组中查找一个
数,返其位置。主程序输入数据,输出排序
结果;输入待查找的数,显示查找结果。
q分析:
int const len=6;
int array[len];
bubble();对数组中的数据按升序排序
find(int num);在数组中查找
num,返回位置
函数之间的数据传递
函数bubble()对数组中的数据按升序排序
int const len=6;
int array[len]; //定义全局变量
void bubble(); //函数声明
int find(int num); //函数声明
void main(void)
{ int i,num;
for (i=0; i<len; i++)
cin>>array[i]; //53 2 6 4 31 12
bubble(); //对数组array中的数,排序
for (i=0; i<len; i++) cout <<array[i]<<“";
cout <<"\n";
cin>>num; //输入要查找的数
cout<<"The position of "<<num<<" is
"<<find(num)<<endl;
} 31
void bubble()
{ int i,temp, sorted, j;
for(j=1; j<len; j++){
sorted = 1;
for(i=0; i<len-j; i++){
if(array[i]>array[i+1]) {
temp = array[i]; array[i] = array[i+1];
array[i+1] = temp; sorted = 0; }
}
if(sorted)
break; //若本轮没有交换,则提前完成排序
}
} 32
函数find(int num)查找num在数组中位置
改进的程序: 数组作为函数的形参
int find(int num)
{ int mid, low=0, high=len;
while(low<=high){
mid = (low+high)/2;
if(num==array[mid])
return mid;
else if(num<array[mid]) high = mid-1;
elselow = mid+1;
}
if(num!=array[mid])
return -1;
}
问题:用全局变量
array,增加了函数之间的关联性(命名、数
据更新),降低了模块之间的独立性
33
#include <iostream>
using namespace std;
void bubble(int a[], int len);
int find(int a[], int len, int num);
void main(void)
{ int const len=6;
int array[len],i,num;
for (i=0;i<len;i++)
cin>>array[i]; //53,2,6,4,31,12
bubble( array, len);
for (i=0;i<len;i++) cout<<array[i]<<" ";
cout <<"\n"; cin>>num;
cout<<“The position of ”<<num;
cout<<" is "<<find(array,len,num)<<endl;
} 34
函数bubble:采用冒泡法排序
函数find(int num)查找num在数组a中位置
void bubble(int a[], int size) int find(int a[],int len, int num)
{ int i,temp, sorted, j; {
for(j=1; j<size; j++){ int mid, low=0, high=len;
sorted = 1; while(low <=high){
for(i=0; i<size-j; i++){ mid = (low+high)/2;
if(a[i]>a[i+1]) { if(num ==a[mid])
temp = a[i]; a[i] = a[i+1]; a[i+1] = temp; return mid;
sorted = 0; } else if(num <a[mid]) high = mid-1;
} else low = mid+1;
if(sorted) }
break; if(num !=a[mid])
} return -1;
} 35} 36
函数之间的数据传递
几个通知
q调用函数向被调用函数传递数据
q周五:计算概论部分期中考试,
1小时
|实在参数向形式参数的单向传递
q11月17日上午10:00--12:00,在软件机
|按位置结合
房,程序设计上机考
q被调用函数向调用函数的数据传递
|机考期间,若有外部的
IP用学生帐号登陆,系统
有记录,按作弊处理。
|函数的返回值
|禁用网络作弊:邮件、
QQ
|形式参数为数组类型:双向传递
q答疑
q全局变量
|时间:周二
/五晚:
7:00-9:00
q要保持局部变量的值
|参加者:认为需要帮助的
|定义静态变量:
static
3738
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -