培训演讲稿二.ppt

上传人:本田雅阁 文档编号:3201984 上传时间:2019-07-30 格式:PPT 页数:35 大小:996.02KB
返回 下载 相关 举报
培训演讲稿二.ppt_第1页
第1页 / 共35页
培训演讲稿二.ppt_第2页
第2页 / 共35页
培训演讲稿二.ppt_第3页
第3页 / 共35页
培训演讲稿二.ppt_第4页
第4页 / 共35页
培训演讲稿二.ppt_第5页
第5页 / 共35页
点击查看更多>>
资源描述

《培训演讲稿二.ppt》由会员分享,可在线阅读,更多相关《培训演讲稿二.ppt(35页珍藏版)》请在三一文库上搜索。

1、2019/7/30,主讲人:曹宣俊,C+面向对象程序设计,2019/7/30,目录,指针 常用字符串处理函数 函数 课后习题,2019/7/30,指针,指针是一种数据类型,具有指针类型的变量称为指针变量。一个指针变量所存储的信息是一个对象在内存中的地址。通过指针可以间接地访问对象。 每一个指针变量都有一个相应的基类型。基类型用以说明这个指针所指向的地址中存放数据的数据类型。,2019/7/30,指针,基类型* 指针变量 int *pi 指向int型的指针 float* pl;指向float型的指针 char* pc;指向char型的指针 char (*pa)3指向一维数组的指针 int (*p

2、f)();指向函数的指针 int *pp;指向指针的指针,2019/7/30,指针,一个指针所占的内存空间大小与一个内存地址所占空间相等 32位机器中指针占有四个字节 即int* pi 和double* pd都一样都占有四个字节,2019/7/30,指针的用法,错误用法一 int* p; *p=10; 为什么出错呢?这是因为指针也是一个变量,在执行int* p 语句时,只给p分配了空间,它是一个长度是4个字节的地址空间,并没有分配它指向的空间,也就是说,p的值是一个没有意义的地址值,显然*p也是没有意义的,当执行 *p=10; 语句时肯定出错,改正的方法是先分配平指向的空间,再赋值 int*

3、p=new int; *p=10,2019/7/30,指针的用法,错误用法二 上面的语句是否可以写成这样呢? int* p=10; 注意:p是一个指针变量,不能赋常量值。 但是以下语句是正确的: char* p=“string”; 这是因为计算机先给字符串“string”分配一个空间,并将其首地址赋值给p。但是要注意的是p指向的是单个字符,如以下语句 cout“*p”*pendl; 只输出s,要想输出整个字符串,应该为: cout“p=”pendl;,2019/7/30,指针的用法,前面列举了两种可能误用指针的例子 从前面的例子可以看出指针使用的繁琐, 但是为什么还要使用指针呢? 原因:1 指

4、针和数组相比,如果利用下标访问元素,指针比数组要处理起来快,2019/7/30,一维指针数组的指针表示法,Int a5;/a是一维数组名,它有五个int型变量。 当用指针表示时,*(a+i)与ai(其中,i=1,2,3,4,5)是相同的。常量指针与变量指针是有区别的。例如: int a10,*p; p=a; 表达式p+1,a+2,p=p+1,p-a等都是合法的;而表达式a=a+1,a=a-1等是非法的。为什么?,2019/7/30,二维指针数组的指针表示法,例如: int b23;/b是二维数组名,它有个int型变量 当用指针表示时,*(*(b+i)+j)与bij (其中i=0,1;j=0,1

5、,2)是相同的。一个二维数组可以看成是一个一维数组,即行数组,每个元素(即每个行数组)又是具有3个元素的一维数组,称为列数组。因此,b23可以看成2个元素的一维行数组和3个元素的一维 数组,称为列数组。因此,b23可以看成为2个元素的一维行数组和3个元素的一维列数组组成。前面讲过了一维数组的指针表示,将二维数组的行,列的一维数组都用指针表示,便得到如下形式: *(*(b+i)+j),2019/7/30,二维指针数组的指针表示法,数据的一种重要表现形式,常量的值不可改变, 这是个二级指针。再将二维数组的行数组用下标表示,列数组用指针表示,得到如下形式: *(bi+j) 再将二维数组的行数组用指针

6、表示,列数组用下标表示,又得到如下形式: (*(b+i)j 另外按照二维数组在内存中的排放顺序,用指向数组首元素的一级指针表示如下: *(&b00+3*i+j),2019/7/30,常用字符串处理函数,char* strstr(const char* srcstr,const char* substr); 应用举例: char* substr=“sip:”; char* srcstr=“http:sip:80810.164.204.148:26780;lr.sip:”; char* startstr=strstr(srcstr,substr); char* endstr=strstr(srcs

7、tr.”); int len=endstr-startstr-4; char servicekey8=0; memcpy(servicekey,startstr+4,len) coutservicekeyendl;,2019/7/30,常用字符串处理函数,char* strtok(char*,const char*); char t_sep=“|“; char *ptoken = NULL; char countrycode=“86|89|973“; ptoken = strtok(countrycode , t_sep); bool t_bExist = false; while ( pto

8、ken != NULL ) if ( strcmp(ptoken,“973“) = 0 )/对比国家码 t_bExist = true ; break; ptoken = strtok( NULL, t_sep); / if(t_bExist) cout“存在“endl; else cout“不存在“endl; ,2019/7/30,变量作用域,在C+中,所定义的变量分为局部变量和全部变量 局部变量 局部变量是指作用域在函数级和块级的变量。包含有自动变量(auto)和内部静态变量(static) 以及函数参数 自动变量是定义在函数体内或分程序内,定义时可以加说明符auto,也可以省略,所以,在

9、程序中无特殊说明的变量都默认为自动变量。由于自动变量以堆栈方式占用内存空间,因此在运行到此作用域时,系统会立刻为这个变量分配内存空间,而程序运行后,这个堆栈立即被系统回收,即这个变量会消失。 与自动变量作用域相同的另一种变量是寄存器,这种变量也是定义在函数体内或者分程序内,定义时前面加register。寄存器类变量有可能被存放在CPU的通用内存中,这样可提高存取速度,如果没被存放在通用内存,便会按照自动变量处理。能否存放在通用寄存器中,取决于通用寄存器是否空闲。 定义寄存器变量时,应注意一下几点: (1)该变量的数据长度与通用寄存器的长度相当,一般是char或者int (2)寄存器变量不宜太多

10、,因为通用寄存器数量毕竟有限 (3)要选择使用频率相当的变量作为寄存器变量,例如,多重循环的内重循环变量等。,2019/7/30,变量作用域,内部变量是定义在函数体内或者分程序内,并且用说明符static说明的一种变量。 它的作用和自动变量相同。但是C+编译器以固定地址存放这个变量,而不是以堆栈存放。因此只要整个程序在运行,这个变量就会存在。 内部静态变量定义函数体内,它的作用域定义在它的函数体内或分程序内,然而在定义它的作用域外,虽然不可见,但仍然存在,没有被释放掉,一旦回到它的作用域后,它仍然保留其原有的值。理解了这个特点后,便会分析和选用适当的变量类型了。,2019/7/30,静态变量示

11、例程序,void func(int v) static int value=v; cout“value:“valueendl; func(2); func(4);,2019/7/30,全局变量,全局变量是指作用域在程序级或文件级的变量。包括外部变量和外部静态变量。 外部变量的作用域是程序级的,即在一个文件定义的外部变量,在该程序的其它文件中是可以用的,外部变量定义在函数体外,定义任何存储类型说明,外部变量在引用其需要说明,说明外部变量时应在其前面加说明符extern,表示该变量时外部变量。在一个文件中,先引用后定义的外部变量引用前必须说明,这称为外部变量提前说明,在一个文件中定义的外部变量在另

12、一个文件中要引用,则在其前必须说明。可见,外部变量的定义和说明是两回事,在一个程序中,一个外部变量只能定义一次,但是可以说明多次。 内部静态变量定义时时有默认值的,int为0,浮点型为0.0,char为空。外部变量和外部静态变量也是如此,但是自动变量和寄存器变量定义后没赋值,是不会有默认值的。,2019/7/30,函数,函数的定义和说明 在C+中,定义函数的格式如下 数据类型 函数名(参数表) 语句序列; ,2019/7/30,函数的定义和说明,示例程序 计算1+2+100 int sum(int n) int i,s=0; for(i=1;i=n;+i) s+=i; return s; ,2

13、019/7/30,函数的定义和说明,定义函数时,参数表中的参数称为形式参数,简称形参。形参在该函数被调用时才被初始化。形参的使用将使被调用函数可以从调用函数那里获得数据。如果被调用函数不需要从调用函数那里获得数据,则该函数参数表可以为空。 函数的说明 (1)如果一个函数定义在前,调用在后,则调用前不需要说明 (2)如果定义在后,调用在后,调用前必须说明 说明函数的格式 数据类型 函数名(参数表); 举例:int sum(int);,2019/7/30,函数的调用,函数的调用格式 函数名(实参表); 其中,实参表给出调用函数相对应的实参,当有一个以上的参数时需用逗号分隔,每个参数是一个变量或表达

14、式。 函数调用过程是将实参传给形参,执行函数体后将结果返回。C+中,实参传给形参的方式有如下几种: (1)传值调用 (2)传址调用 (3)引用调用,2019/7/30,传值调用,传值调用时,调用函数的实参,使用常量,变量或者表达式值,被调用函数的形参使用变量值。调用时,系统先计算实参表达式的值,再将实参的值按位置对应的赋值给形参,即对形参进行初始化。因此,传值调用的实现机制是系统将实参备份一个副本给形参。在被调用函数中,形参可以改变,但这只影响副本中的形参值,而不影响调用函数的实参值。所以,传值的调用的特点是形参值的改变不影响实参。,2019/7/30,传值调用示例程序一,void swap(

15、int x,int y) int tmp; tmp=x; x=y; y=tmp; ,2019/7/30,传值调用示例程序二,举例 void fun(int* p) p=new int20; ,2019/7/30,传址调用,使用传址调用方式时,调用函数的实参使用地址值,被调用函数的形参使用指针,。调用时系统将实参的地址赋值给对应的形参指针,使形参指针指向实参变量。因此,传址调用与前面讲过的传值调用不同,它的实现机制是让形参的指针直接指向实参。所以,传址调用时,在被调用函数中,可以通过改变形参指针所指向的实参变量来间接改变实参值。,2019/7/30,传址调用示例程序一,void swap(int

16、 *x,int* y) int tmp; tmp=*x; *x=*y; *y=tmp; ,2019/7/30,传址调用示例程序二,void fun(int* p) *p=new int20; ,2019/7/30,引用调用,使用引用调用时,调用函数的实参要用变量,将实参赋值给形参的引用,相当于使用了实参的别名。于是在被调用函数中,对引用的改变,实质就是直接的通过引用来改变实参的变量值。而且这种调用起到传址调用的作用,但它又比传址调用更方便更直接。,2019/7/30,引用调用示例程序一,void swap(int x=y; y=tmp; ,2019/7/30,函数的参数,函数参数的求值顺序 当

17、一个函数带有多个参数时,C+语言没有规定在函数调用时参数的求值顺序。而编译器根据对代码进行优化的需要自行规定对实参的求值顺序。有的编译器规定自左向右,有的自右向左。一般,求值顺序不会对函数功能有影响。但是,如果实参表达式中带有副作用的运算符时,就有可能产生由于求值顺序不同而造成的二义性。,2019/7/30,函数的参数,示例程序一 int x=4,y=6; int z=add_int(+x,x+y); 其中实参是两个表达式+x和x+y。当编译器对实参求值顺序是自左向右时,两个实参值分别为5和11.当编译器对实参求值顺序自右向左时,两个实参值分别为5和10.,2019/7/30,设置函数参数的默

18、认值,int add_int(int x,int y=10); 在上述对函数add_int()的说明中,对函数的最右边的一个参数指定了默认值。在函数调用时,编译器按从左到右的顺序将实参与形参结合起来,当实参的数目不足时,编译器将按照同样的顺序用说明中的或定义中的默认值来补足所缺少的实参。所以下面的函数调用 add_int(14); 将与下列调用表达式等价 add_int(14,10);,2019/7/30,课后思考,1,打印杨辉三角 1 1 1 1 2 1 1 3 3 1 2,模拟linux命令find name “core*”功能,写一个函数,在指定字符串中查找目标字符串,2019/7/30,Thank You!,2019/7/30,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1