nbhkdz.com冰点文库

12函数


函数

? ? ? ? ?

main() sqrt() strlen() strcmp() strcpy()

#include<iostream> #include<cstring> using namespace std; int main() { char a[100]; cin>

;>a; int len=strlen(a); cout<<len<<endl; return 0; }

调用一个函数就相当于执 行一段代码,这段代码可 以是某个头文件内的,也 可以是自己定义的 int i=0; while(a[i]!=0)i++;

函数的优点
? 代码模块化 重复功能的代码只需要编写一次,修改的时 候,只要改一个地方,方便维护

A+B 高精度 升级版
题目描述
有两个长度不超过1000位的整数,可能是正数,也可能是负数,请计算他们的和。

输入
两行,每行表示一个整数,最高位不是0,如果是负数,前面会有负号

输出
一行,计算的结果

样例输入
9867534210362951847 -10362951847

样例输出
9867534200000000000

本题情况复杂,但如果定义两个函数,问题将变得简单: Add(a,b) 计算a+b的值 Sub(b,a) 计算b-a的值

函数的格式
int main( ) { ...... return 0; }

形式参数列表

返回值类型 函数名(类型 参数1 ,类型 参数2,… ,类型 参数n ) { 函数体 return 语句 }

返回值类型 函数名(类型 参数1 ,类型 参数2,… ,类型 参数n ) { 函数体 return 语句 }
void message ( ) { cout << "How do you do!" << endl ; return ; } double Max ( double x , double y ) { if ( x > y ) return x ; else return y ; }

函数调用
调用形式

函数名 ( 实际参数表 )
与形式参数必须在个数、类型、位置 一一对应

先定义,后调用,函数定义必须位于函数调用之前 message( ) ; m = Max( a, b ); for(int i=0;i<strlen(c);i++){ }

例1

函数返回值类型

函数名

形式参数表

无返回值 #include<iostream>

无参数

using namespace std; void message ( ) { cout << "How do you do!" << endl ; return ; } int main( ) { message( ) ; return 0; }
函数调用语句 函数体

例2 #include<iostream>
using namespace std;

函数返回值类型

函数名

形式参数表

double Max ( double x , double y ) { if ( x > y ) return x ;

else
return y ; }

函数体

int main()
{ double a, b; cin >> a >> b ; double m = Max( a, b ); cout << Max( m, 3.5 ) << endl ; return 0; } 调用函数 实际参数

函数调用返回的过程
#include<iostream> using namespace std; int main() { double a,b,c; cin>>a>>b; c=Max(a,b); cout<<c; return 0; }





double Max( double x, double y ) { if ( x > y ) return x ; ② else return y ; }

①保留现场,记录当前程序执行的位置,传递参数 ②执行函数 ③返回return 语句后的变量,回到原函数离开的位置 继续执行

返回值可以为空(void),此时return语 句可以省略,也可直接写 return; 所有程序,从main()函数开始执行,函 数的命名与变量的命名类似,不得重名

返回值类型 函数名(类型 参数1 ,类型 参数2,… ,类型 参数n ) { 返回值类型不为空,函数体内必须包含 函数体 return语句,返回变量的类型与函数所指 return 语句 定的返回值类型要一致 }

调用的时候,实际参数表必须 与形式参数
必须在个数、类型、位置一一对应

double Max ( double x , double y )

{ if ( x > y )
return x ; else

return y ;
}
return 语句形式: return 表达式 作用: ? 返回函数执行结果值 ? 不再执行后续语句,函数执行结束,返回调用

此函数的位置
一个函数体内可以有多个return 语句

函数调用注意事项
? 返回值类型为void - 只能单独调用
void message ( ) { cout << "How do you do!" << endl ; return ; } int main( ) { message ( ); int c= message ( ); cout<< message ( ); Max(3.8,4.9); double d=Max(5.9,6.7); cout<<Max(Max(1.2,5),8.9); }

? 返回值类型不是void 赋值语句右边,条件表达式,函数参数, 输出语句…
double Max ( double x , double y ) { if ( x > y ) return x ; else return y ; }

变量作用域
#include<iostream> using namespace std; int a,b[10]; int abs(int x) { if(x<0)return –x; else return x; } int main( ) { int c,d[20]; cin>>c; c=abs(c); ....... return 0; }
全局变量,所有函数中都可以访问

形式参数,只有在abs中可以访问

c,d 只有在main函数可以访问

变量作用域
1.全局变量 全局变量的作用域是从变量定义的位置起直至源文件结束止,即从 定义位置之后的所有函数都可以访问该全局变量。

? 使用全局变量的说明: ? 在一个函数内部,既可以使用本函数定义的局部变量,也可以使用在 此函数前定义的全局变量。 ? 如果多个函数都要对同一个变量进行处理,就可以将此变量定义成全 局变量。 ? 过多地使用全局变量,会增加调试难度。 ? 全局变量在程序执行的全过程中一直占用内存单元。 ? 全局变量在定义时若没有赋初值,其默认值为0。

? 2.局部变量 ? ⑴局部变量的作用域是在定义该变量的函数内部。局部变量只在定 义它的函数内有效,函数的形参也是局部变量。 ? ⑵在不同的函数中变量名可以相同 ? ⑶一个局部变量和一个全局变量是可以重名的,在相同的作用域内 局部变量有效时全局变量无效。

在那一对花括号内定义的变量,只在这一对花括号内 有效。 不包含在任何花括号内的变量,就是全局变量,全局 从定义的地方起,到代码结束,都有效。 for循环内定义的循环变量,只在这个循环内有效。

看程序,说结果:

#include<iostream> using namespace std; int b,c; void f() { b=10;} int main() { int a=200; for(int a=1;a<2;a++) cout<<a<<endl; cout<<a<<endl; cout<<b<<endl; f(); cout<<b<<endl; int b=50; cout<<b<<endl; return 0; }

看程序,找错误:
#include<iostream> using namespace std; int main() { while(1) { int i=1; while(1) { int j=2; cout<<j<<endl; break; } cout<<j<<endl; cout<<i<<endl; break; } cout<<i<<endl; return 0;

}

自定义strlen函数
#include<iostream> using namespace std; int strlen (char a[ ]) { int i=0; while(a[i]!=0)i++; return i; } int main( ) { char b[200],c[200]; cin>>b; int d=strlen(b); cout<<d<<endl; cin>>c; cout<<strlen(c)<<endl; return 0; }
作为形式参数时,数组的大 小可以省略

i的类型必须与strlen 函数返回值类型一致

b,c数组的首地址复制 给strlen的形式参数a

排序
#include<iostream> using namespace std; void sort (int a[ ],int len) { for(int i=0;i<len-1;i++) { for(int j=i+1;j<len;j++) if(a[i]>a[j]) { int t=a[i]; a[i]=a[j]; a[j]=t; } } return ; } int main( ) { int n,a[100]; cin>>n; for(int i=0;i<n;i++)cin>>a[i]; sort(a,n); for(int i=0;i<n;i++)cout<<a[i]<<' '; return 0; }

main函数中的数组a与 形式参数a同名,但 sort函数不能直接访问 main函数中的数组a

调用sort时,main中 的a数组的首地址复制 给sort函数的形式参数 a;sort无法知道传递 过来的参数a的元素个 数,也不知道应该对多 少个元素进行排序,所 以加入形式参数len

内存地址

1bit 一位二进制0或者1 8bit=1Byte(字节) 内存最小存储单元 1024Byte=1KB 1024KB=1MB 1024MB=1GB

内存地址
? 2GB=2X1024X1024X1024=231Byte
每一个存储单元,都有一个唯一的内存地址

第一个存储单元(Byte 字节)地址是:0

内存

第二个存储单元:1 第三个存储单元:2 第四个存储单元:3

...........
第231个存储单元: 231 -1

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

变量内存地址
int a

char b

变量或数组的地址,指 的是该变量或数组所占 内存空间的首地址

char c[8];

程序运行时内存的分配与释放:
计算机内存由操作系统统一管理 分配:程序运行时,需要向操作系统申请使用内存,由操 作系统划分一块空闲的内存区域给这个程序; 释放:程序运行结束后,要将自己占用的内存还给操作系 统。

例如:假设有100个存储单元,操作系统有一个程序,MemoryManager,负责管 理内存 0 5 MemoryManager占用 10 20 30 40 50 60 70 80 90 9 请问有多少内存是空闲的? 系统运行时,发生如下 有多少内存被占用? 事件: 1,A程序申请50个存储 单元

2.程序B,申请30个存储 单元
3.程序A释放,50个存储 单元

3.程序C,申请30个存储 单元

例如:假设有100个存储单元,操作系统有一个程序,MemoryManager,负责管 理内存 0 5 MemoryManager占用 10 20 30 40 50 60 70 80 90 9 请问有多少内存是空闲的? 系统运行时,发生如下 有多少内存被占用? 事件: 1,A程序申请50个存储 单元

A程序

2.程序B,申请30个存储 单元
3.程序A释放,50个存储 单元

3.程序C,申请30个存储 单元

例如:假设有100个存储单元,操作系统有一个程序,MemoryManager,负责管 理内存 0 5 MemoryManager占用 10 20 30 40 50 60 70 80 90 9 请问有多少内存是空闲的? 系统运行时,发生如下 有多少内存被占用? 事件: 1,A程序申请50个存储 单元

A程序

2.程序B,申请30个存储 单元
3.程序A释放,50个存储 单元

3.程序C,申请20个存储 单元

B程序

例如:假设有100个存储单元,操作系统有一个程序,MemoryManager,负责管 理内存 0 5 MemoryManager占用 10 20 30 40 50 60 70 80 90 9 请问有多少内存是空闲的? 系统运行时,发生如下 有多少内存被占用? 事件: 1,A程序申请50个存储 单元

2.程序B,申请30个存储 单元
3.程序A释放,50个存储 单元

3.程序C,申请30个存储 单元

B程序

例如:假设有100个存储单元,操作系统有一个程序,MemoryManager,负责管 理内存 0 5 MemoryManager占用 10 20 30 40 50 60 70 80 90 9 请问有多少内存是空闲的? 系统运行时,发生如下 有多少内存被占用? 事件: 1,A程序申请50个存储 单元

C程序

2.程序B,申请30个存储 单元
3.程序A释放,50个存储 单元

3.程序 C,申请30个存储 如果此时,又有一 单元

B程序

个程序D要申 请50个存储单元, 那会怎么样呢?

C++内存分配规律
? 以函数为单位 ? 函数调用时,分配空间 ? 函数执行结束时,释放空间

#include<iostream> Using namespace std; Int main() { double a,b,c; cin>>a>>b; c=Max(a,b); cout<<c; return 0; }





double Max( double a, double b ) { if ( a > b ) return a ; ② else return b ; }

内存: Main函数 a,b,c

执行Max函数 Max函数 a,b

执行main函数

Max执行完成, 释放Max的空 间

函数参数传递
非引用参数 普通的非引用类型的参数是通过复制对应的实参实现初始化。 当用参数副本初始化形参时,函数并没有访问调用所传递的实参本身 ,因此不会修改实参的值。举个例子:
#include<iostream> using namespace std; void swap(int a,int b) { int tmp=a;a=b;b=tmp; } int main() { int c=1,d=2; swap(c,d); cout<<c<<' '<<d<<endl; return 0; }

在此例中,虽然在swap函数中交换了a,b两数的值,但是在main中却没有 交换。因为swap函数只是交换c,d两变量副本的值。

函数参数传递
引用
引用就是某一变量的一个别名,对引用的操作与对变量直接 操作完全一样。
声明一个引用,不是定义了一 个新变量,它只是给右边的变 量起一个别名

&在此不是求地址运算,而 是起标识作用。

引用的声明方法: 类型标识符& 引用名=变量名; 声明引用时,必须同时对 如:int a=5; int& b = a; 其进行初始化。
类型标识符,限定所能引 用的变量类型,比如b只能 是整型变量的引用

引用,使右边的变量有两 个名称,即原名和引用名 ,且不能再把该引用名作 为其他变量的别名。a是原 名,b是别名,对b的修改 相当于对a修改。

#include<iostream> #include<stdio.h> using namespace std; int main( ) { int n=5; cout<<"n="<<n<<endl; int& t1=n; t1=123; cout<<"n="<<n<<endl; int t2=n; t2=456; cout<<"n="<<n<<endl; cout<<"n's memory address:"<<(int)&n<<endl; cout<<"t1's memory address:"<<(int)&t1<<endl; cout<<"t2's memory address:"<<(int)&t2<<endl; char d[]="abcdef"; cout<<"char d[]:"<<d<<endl; char& c=d[0]; c='z'; cout<<"char d[]:"<<d<<endl; //int& b; //double& b=n; return 0; }

? 引用参数 引用参数直接关联到其所绑定的对象,而并非这些对象的副本。 定义引用时,必须用与该引用绑定对象初始化该引用。引用形参完全 以相同的方式工作。每次调用函数,引用形参被创建并与相应实参关 联。
#include<iostream> “引用”参数, using namespace std; 可以修改main 函数内变量的值 void swap(int& a,int& b) { int tmp=a;a=b;b=tmp; } int main() { int c=1,d=2; swap(c,d); //交换变量 cout<<c<<' '<<d<<endl; return 0; } //程序输出为:2 1

在此例中,因为swap函数的参数为引用参数,所以,在函数swap 中修改a,b的值相当于在主函数main中修改c,d的值。

数组参数: 数组作为参数,在调用的时候,编译器会将数组首地址,复制给形式 参数,通过地址来操作,不会复制整个数组的元素。所以形式参数和实际 参数指向同一块内存空间。
数组名,就是数组的首地址
#include<iostream> using namespace std; int main() { int a[10]={0,1,2,3,4,5,6,7,8,9}; for(int i=0;i<10;i++) cout<<(int)(&a[i])<<' ';//&取地址符号 cout<<endl; cout<<(int)a<<endl;//数组首地址 for(int i=0;i<10;i++) cout<<(int)(a+i)<<' ';//a+i,是a[i]的地址 cout<<endl; return 0; }

int main( ) { int n,a[100]; cin>>n; for(int i=0;i<n;i++)cin>>a[i]; sort(a,n); for(int i=0;i<n;i++)cout<<a[i]<<' '; return 0; }
a是int数组,每个元素占四个字节 b,i都是int变量,占四个字节

void sort (int b[ ],int len) { for(int i=0;i<len-1;i++) { for(int j=i+1;j<len;j++) if(b[i]>b[j]) {int t=b[i]; b[i]=b[j]; b[j]=t;} } } b保存的是一个地址,是 main数中a数组首地址 执行sort函数

内存:
每个方格代表1个字节

Main函数 a i 执行main函数 n



sort函数 b i t

len j

C++访问数组的方式
? 任何变量都是通过地址来访问的 ? 数组由多个元素组成,每个元素都有内存地址,要访 问数组中的某个元素,必须得到这个元素的地址 ? 得到数组内某一元素地址的方式:首地址+偏移量
a是它 的地址
每个方格代表4个字节

int a[10]:
a[0] a[1] a[2] a[3]

a[i]的地址:a + i
注意:实际上,编译器通过计算a+sizeof(int)*i来得到a[i]地址

int a[10]={1,2,4,65,100}; 下标就是偏移量 a[1]=9; for(int i=0;i<10;i++)cout<<a[i]<<‘ ‘;
数组名就是首地址

int main( ) { char b[20]=“abcdefg123”; int d=strlen(b); cout<<d<<endl; int e=strlen(b+2); cout<<e<<endl; return 0; }

int strlen (char a[ ]) { int i=0; while(a[i]!=0)i++; return i; }

a

b

c

d

e

f

g

1

2

3

\0

第一次:strlen(b)

int strlen (char a[ ]) { int i=0; while(a[i]!=0)i++; return i; }

a是b数组第0 个元素的地址

a + i是b数组中那个元 素的地址?
d e f g 1 2 3 \0

a

b

c

a+i =b+i

第二次:strlen(b+2)

int strlen (char a[ ]) { int i=0; while(a[i]!=0)i++; return i; }

a是b数组第2个 元素的地址 a=b+2

a + i是b数组中那个元 素的地址?
f g 1 2 3 \0

a

b

c

d

e

a + i = i + b +2

练习
? 编写一个求长方形面积的函数 area() 长和宽是参数,返回面积

int a[3]={1,2,3}; a[1] int n=0;

n

越界访问

1

2

3

0

a[0]

a[2]

#include<iostream> using namespace std; int main() { int a[3]={1,2,3}; int n=0; cout<<n<<endl; a[3]=4; cout<<n<<endl; return 0; }

编写一个程序,它使用下列函数: Fill_array()将一个double数组的名称和长度作为 参数。它提示用户输入double值,并将这些值存储到数 组中。当数组填满(最多不超过10个)或用户输入了非数 字时,输入将停止,并返回实际输入了多少个数字。 Show_array()将一个double数组的名称和长度 作为参数,并显示该数组的内容。 Reverse_array()将一个double数组的名称和长 度作为参数,并将存储在数组中的值的顺序反转。 Main函数将 调用Fill_array()输入数组 调用Show_array()输出数组; 调用Reverse_array()反转数组; 调用Show_array()输出数组; 调用Reverse_array()反转数组中除第一个和最 后一个元素之外的所有元素, 调用Show_array()输出数组;

? 1169: 分解因式 定义int F(int N){ } 统计N的约数个数 ? 1037: 算式问题 定义bool isok(int t){ } 判断t的每一位是不是输入中出现的, 如果是返回true,否则返回false ? 1069: 字符统计
int count(char s[],int& digit,int& upcase,int& lowercase){ }

统计s中,数字、大写字母,小写字母的个数,并返回长度 digit,upcase,lowercase都是引用参数,它是main内某些变 量的引用 ? 1107: 火柴棒等式 int count(int t){ }计算t需要的火柴数量

? 1145: 贪婪的送礼者 定义:int find(char name[][15],char s[]){ } 查找s在name中的位置,返回行下标,注意数组在作为参 数时第一维的下标可以省略 ? 1059: A+B 高精度 升级版
A + B + |A|,|B| 大小关系 方法 加法 A+B 运算结果负 号 +

+ -

+ |A|>|B| |A|<|B| |A|>|B|

加法
减法 减法 减法

|A|+|B|
A-|B| |B|-A |A|-B

+ -

|A|<|B|

减法

B-|A|

+

int cmp(char A[],char B[]){} 传过来的A,B前没有’-’号 比较大小,如果A>B,返回1;如果A<B,返回-1;如果A==B,返回0 void add(char a[],char b[]){}计算a+b,并输出结果 void sub(char a[],char b[]){}计算a-b,输出结果,传过来的参数要求a>b


12个基本初等函数的导数公式

12个基本初等函数的导数公式_研究生入学考试_高等教育_教育专区。这里将列举 12 个基本初等函数的导数以及它们的推导过程,初等函数的导 数可由之推算。函数函数...

12函数综合

12函数综合_数学_高中教育_教育专区。中考一轮复习总结版 个性化教案 函数综合适用学科 适用区域 知识点 教学目标 教学重点 教学难点数学 人教版 1.二次函数 掌握...

12.1函数练习(一)及答案

12.1函数练习(一)及答案_数学_高中教育_教育专区。12.1 函数练习一 1. 指出下列关系中的变量和常量:①周长C与半径r的关系式是 C ? 2?r ;常量是 ___,...

12.1函数(教学设计)

12.1函数(教学设计)_初二数学_数学_初中教育_教育专区。沪科版八年级数学上册,函数概念,市数学优秀课评比课教学设计今日推荐 50份文档 2014...

12函数1(函数图象)

12函数1(函数图象)_初三数学_数学_初中教育_教育专区。初三数学复习检测题(函数—函数的图象)一、选择题 1、 (2013 年潍坊市)用固定的速度向如图所示形状的杯子...

12函数的应用

12函数的应用_初三数学_数学_初中教育_教育专区。林语书海, 翰写未来!函数的应用一、知识要点概述 命题趋势分析: 函数是初中数学的重点,也是难点,更是中考命题的...

12.1函数(1)

课题:第 12 章一次函数 12.1 函数(1)主备人:赵催催、施冰红 审核人: 杨杰 时间:2013 年 9 月 学习目标: 1.了解常量、变量的意义,能分清实例中出现的...

函数12分段函数

函数12分段函数_数学_自然科学_专业资料。函数(十二)分段函数姓名: 一、基础知识 1、若一个函数的定义域分成了若干个子区间,而每个子区间的解析式不同,这种函数称...

12-函数的应用

2页 10财富值 第12课 一次函数及其应用 46页 5财富值如要投诉违规内容,请到百度文库投诉中心;如要提出功能问题或意见建议,请点击此处进行反馈。 ...