第7章间接访问指针ppt课件.ppt

上传人:本田雅阁 文档编号:3132305 上传时间:2019-07-15 格式:PPT 页数:109 大小:870.52KB
返回 下载 相关 举报
第7章间接访问指针ppt课件.ppt_第1页
第1页 / 共109页
第7章间接访问指针ppt课件.ppt_第2页
第2页 / 共109页
第7章间接访问指针ppt课件.ppt_第3页
第3页 / 共109页
第7章间接访问指针ppt课件.ppt_第4页
第4页 / 共109页
第7章间接访问指针ppt课件.ppt_第5页
第5页 / 共109页
点击查看更多>>
资源描述

《第7章间接访问指针ppt课件.ppt》由会员分享,可在线阅读,更多相关《第7章间接访问指针ppt课件.ppt(109页珍藏版)》请在三一文库上搜索。

1、第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,指针介绍,本章将介绍C+语言的一个重要的特性:指针,为了成为一个优秀的C+语言程序员,你必须掌握指针并熟练地使用它们。,指针 是内存的地址并可作为数据 是一个灵活和危险的机制 允许共享处理数据 允许内存动态分配(只要需要,而非预先定义),指针的概念,指针就是把地址作为数据处理 指针变量:存储地址的变量 变量的指针:当一个变量存储另一个变量的地址时,那我们说它就是那个变量的指针 使用指针的目的:提供间接访问,指针的概念 续,如在某一程序中

2、定义了 int x = 2; 如系统给x分配的空间是1000号单元,则指向x的指针是另一个变量p,p中存放的数据为1000 1000号单元的内容有两种访问方式: 访问变量x(直接访问) 访问变量p指向的单元的内容(间接访问),定义指针变量,定义指针变量要告诉编译器该变量中存放的是一个地址。 指针变量的主要用途是提供间接访问,因此也需要知道指针指向的单元的数据类型 指针变量的定义 类型标识符 *指针变量; 如:int *intp; double *doublep; int *p, x, *q;,指针变量的操作,如何让指针指向某一变量?因为我们不知道系统分配给变量的真正地址是什么。 用地址运算符

3、“ & 运算符后面不能跟常量或表达式。如 &2 是没有意义的,&(m * n + p )。也是没有意义的 如何通过指针变量处理和改变它所指向的单元的值? 用引用运算符 “*” 解决。如 *intp 表示的是 intp 指向的这个单元的内容。如:*intp = 5 等价于 x = 5 在对 intp 使用引用运算之前,必须先对 intp 赋值,指针实例,如有: int X, *intp, Y; X=3; Y=4; intp=,如执行: *intp=Y+4;,注意:不能用 intp=100; 因为我们永远不知道变量存储的 真实地址,而且程序每次运行变量地址可能都不同。,指针使用,指针变量可以指向不

4、同的变量。如上例中intp指向x,我们可以通过对intp的重新赋值改变指针的指向。如果想让intp指向y,只要执行intp=&y就可以了。这时,intp与x无任何关系。 同类的指针变量之间可相互赋值,表示二个指针指向同一内存空间。 空指针 指针没有指向任何空间 空指针用常量NULL表示,NULL的值一般赋为0 不能引用空指针指向的值,指针变量的使用,设有定义 int x, y; int *p1,*p2;,执行语句: x=23; y=234;,执行语句: p1=,执行语句: *p1=34; p2=p1;,指针实例,有以下结构,比较执行 p1=p2和 *p1= *p2后的不同结果。,指针的初始化,

5、指针在使用前必须初始化。 和别的变量一样,定义指针不初始化是一个比较普通的错误。 没有初始化的指针可能指向任意地址,对这些指针作操作可能会导致程序错误。 NULL是一个特殊指针值,称为空指针。它的值为0。它可被用来初始化一个指针,表示不指向任何地址。 思考:int *p; *p = 5; 有什么问题?,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,指针运算和数组,指向数组元素的指针 数组元素是一个独立的变量,因此可以有指针指向它。如:p = &a1, p = &ai 数组元素的地址

6、是通过数组首地址计算的。如数组的首地址是 1000,则第i 个元素的地址是1000 + i * 每个数组元素所占的空间长度,指针与数组,在C+中,指针和数组关系密切,几乎可以互换使用 数组名可以看成是常量指针,对一维数组来说,数组名是数组的起始地址,也就是第0个元素的地址 如执行了p=array,则p与array是等价的,对该指针可以进行任何有关数组下标的操作,例如:有定义 int a10, *p 并且执行了 p=a, 那么可用下列语句访问数组a的元素 for ( i=0; i10; +i ) cout pi;,指针运算,指针+1表示数组中指针指向元素的下一元素地址; 指针-1表示数组中指针指

7、向元素的上一元素地址; 合法的指针操作:p + k, p - k, p1 - p2,指针保存的是一个地址,地址是一个整型数,因此可以进行各种算术运算,但仅有加减运算是有意义的。指针运算与数组有密切的关系,数组元素的指针表示,当把数组名,如 intarray,赋给了一个同类指针intp 后,intarray 的元素可以通过intp访问。第i个元素的地址可表示为 intp + i,第i个元素的值可表示为 *(intp + i)。 通过指针访问数组时,下标有效范围由程序员自己检查。 如输出数组 a 的十个元素,方法3: for ( p=a; pa+10; +p ) cout *p ;,方法2: fo

8、r ( i=0; i10; +i ) cout *(a+i);,方法1: for ( i=0; i10; +i ) cout ai;,方法4: for ( p=a, i=0; i10; +i ) cout *(p+i);,方法5: for ( p=a, i=0; i10; +i ) cout pi ;,下列程序段 有无问题? for ( i=0; i10; +i ) cout *a ; +a; ,指针和数组的区别,虽然通过指针可以访问数组,但两者本质是不同的。 在定义数组时为数组的各个元素分配了全部的存储区,而在定义指针时,仅仅分配四个字节的存储区存放指针地址。只有把一个数组名付给了对应的指针

9、后,指针才能当作数组使用 如有:int array5, *intp;,当执行了 intp = array 后,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,动态分配,在C+语言中,每个程序需要用到几个变量,在写程序前就应该知道。每个数组有几个元素也必须在写程序时就决定。 有时我们并不知道我们需要多大的数组元素直到程序开始运行。因此希望能在程序中根据某一个当前运行值来决定数组的大小。如设计一个打印魔阵的程序,我们希望先输入魔阵的阶数,然后根据阶数定义一个矩阵,动态分配方法,这些问题的

10、解决方案就是内存的动态分配。我们定义一个指针,并让它指向一个合适的内存。如: int *scores; scores = 内存的起始地址;,动态内存分配与回收,中由new 和 delete两个运算符替代 - 运算符new用于进行内存分配: 申请动态变量:p = new type; 申请动态数组:p = new typesize; 申请动态变量并初始化:p = new type(初值); - 运算符delete 释放 new分配的内存: 释放动态变量:delete p; 释放动态数组:delete p;,动态内存分配与回收,/为简单变量动态分配内存,并作初始化 int main() int *p

11、; p = new int(99); /动态分配内存,并将99作为初始化值赋给它 cout *p; delete p; return 0; ,动态内存分配与回收,/动态字符串的使用 int main() int *p; char *q; p = new int(5); q = new char10; strcpy(q, “abcde“); cout *p endl; cout q endl; delete p; delete q; return 0; ,输出结果: 5 abcde,动态分配的检查,new操作的结果是申请到的空间的地址 当系统空间用完时,new操作可能失败 new操作失败时,返回

12、空指针,动态内存分配与回收,/动态分配检查 int main() int *p; p = new int; if(!p) cout “allocation failuren“; return 1; *p = 20; cout *p; delete p; return 0; ,assert宏,assert()宏在标准头文件cassert中 assert()有一个参数,表示断言为真的表达式,预处理器产生测试该断言的代码。如果断言不是真,则在发出一个错误消息后程序会终止。,#include #include /包含assert宏的头文件 using namespace std; int main()

13、 int *p; p = new int; assert (p != 0); /p等于0,则退出程序 *p=20; cout *p; delete p; return 0; ,内存分配的进一步介绍,静态分配:对全局变量和静态变量,编译器为它们分配空间,这些空间在整个程序运行期间都存在 自动分配:函数内的局部变量空间是分配在系统的栈工作区。当函数被调用时,空间被分配;当函数执行结束后,空间被释放 动态分配:在程序执行过程中需要新的存储空间时,可用动态分配的方法向系统申请新的空间,当不再使用时用显式的方法还给系统。这部分空间是从被称为堆的内存区域分配。,内存泄漏,动态变量是通过指针间接访问的。如果

14、该指针被修改,这个区域就被丢失了。堆管理器认为你在继续使用它们,但你不知道它们在哪里,这称为内存泄露。 为了避免出现孤立的区域,应该明白地告诉堆管理器这些区域不再使用。可以采用delete操作,它释放由new申请的内存。 当释放了内存区域,堆管理器重新收回这些区域,而指针仍然指向堆区域,但不能再使用指针指向的这些区域。 要确保在程序中同一个区域释放一次。 释放内存对一些程序不重要,但对有些程序很重要。如果你的程序要运行很长时间,而且存在内存泄漏,这样程序会耗尽所有内存,直至崩溃。,动态空间分配示例,输入一批数据,计算它们的和。数据个数在设计程序时尚无法确定。 存储一批数据应该用数组,但C+语言

15、的数组大小必须是固定的。该问题有两个解决方案: 开设一个足够大的数组,每次运行时只使用一部分。缺点:浪费空间 用动态内存分配根据输入的数据量申请一个动态数组,#include using namespace std; int main() int *p, i, n, sum=0; cout n; if (!(p = new int n) exit(1); for (i=0; i pi; for(i=0; in; +i) sum += pi; delete p; cout “Number of elements:“ n endl; cout “Sum of the elements:“ sum

16、endl; return 0; ,可改为: p = new int n; assert( p != NULL);,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,字符串再讨论,字符串的另一种表示是定义一个指向字符的指针。然后直接将一个字符串常量或字符串变量赋给它 如 char *String, ss =“abcdef”; String = “abcde”; String = ss;,String = “abcde”;的执行结果,字符串常量存储在一个称为数据段的内存区域里 将存储字符串

17、”abcde”的内存的首地址赋给指针变量String。,String = ss的执行过程,将字符数组ss的起始地址存入String,String = new char5; strcpy(String, “aaa”),动态变量存储在堆工作区 将存储字符串”aaa”的内存的首地址赋给指针变量String。,用指针表示的字符串的操作,可以直接作为字符串操作函数的参数。但必须注意,如果该指针指向的是一个字符串常量时,则使用是受限的。如不能作为strcpy的第一个参数 由于在C+中,数组名被解释成指向数组首地址的指针。因此,字符串是用一个指针变量表示,我们可以把此指针变量解释成数组的首地址,通过下标访问

18、字符串中的字符。如string3的值是d。,用指针处理串,目的:编写一个记录串中单词的个数的函数。 关键技术:要传递一个字符串给函数,字符串作为函数的参数,字符串作为函数的参数和数组名作为参数传递一样,可以有两种方法 作为字符数组传递 作为指向字符的指针传递 两种传递方式的本质是一样的,都是传递了字符串的首地址 字符串作为字符数组传递时不需要指定长度。因为字符串操作的结束是依据0,#include Using namespace std; int word_cnt(const char *s) int cnt = 0; while (*s != 0) while (isspace(*s) +s

19、; /跳过空白字符 if (*s != 0) +cnt; /找到一个单词 while (!isspace(*s) ,统计字符串中单词数的函数,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,指针作为函数参数和返回值,指针作为函数参数 数组名作为函数参数 返回指针的函数 引用和引用传递 返回引用的函数,指针作为函数参数,例:编一函数,交换二个参数值。,void swap(int a, int b) int c; c=a; a=b; b=c; ,希望通过调用swap(x, y)交换变量x

20、和y的值,新手可能会编出如下的函数:,因为C+采用的是值传递机制,函数中a、b值的交换不会影响实际参数x和y的值,void swap(int *a, int *b) int c; c=*a; *a= *b; *b=c; ,交换x和y的值,可以调用swap(&x, &y),用指针作为参数可以在函数中修改主调程序的变量值,即实现变量传递。必须小心使用!,正确的方法,能解一元二次方程的函数,目前为止我们了解到的函数只能有一个返回值,由return 语句返回。 一个一元二次方程有二个解,如何让此函数返回二个解。答案是采用指针作为函数的参数。 由调用程序准备好存放两个根的变量,将变量地址传给函数。在函数

21、中将两个根的值分别放入这两个地址,函数原型,函数原型可设计为: void SolveQuadratic(double a, double b, double c, double *px1, double *px2) 函数的调用 SolveQuadratic(1.3, 4.5, 2.1, &x1, &x2) SolveQuadratic(a, b, c, &x1, &x2) 函数的参数有两类:输入参数和输出参数。一般,输入参数用值传递,输出参数用指针传递。在参数表中,输入参数放在前面,输出参数放在后面。,原型的改进,并不是每个一元二次方程都有两个不同根,有的可能有两个等根,有的可能没有根。函数的

22、调用者如何知道x1和x2中包含的是否是有效的解? 解决方案:让函数返回一个整型数。该整型数表示解的情况,完整的函数,int SolveQuadratic(double a,double b,double c, double *px1,double *px2) double disc, sqrtDisc; if(a = 0) return 3; /不是一元二次方程 disc = b * b - 4 * a * c; if( disc 0 ) return 2; /无根 if ( disc = 0 ) *px1 = -b /(2 * a); return 1; /等根 /两个不等根 sqrtDis

23、c = sqrt(disc); *px1 = (-b + sqrtDisc) / (2 * a); *px2 = (-b - sqrtDisc) / (2 * a); return 0; ,函数的调用,int main() double a,b,c,x1,x2; int result; cout a b c; result = SolveQuadratic(a, b, c, ,指针作为函数参数和返回值,指针作为函数参数 数组名作为函数参数 返回指针的函数 引用和引用传递 返回引用的函数,数组传递的进一步讨论,数组传递的本质是地址传递,因此形参和实参可以使用数组名,也可以使用指针。 数组传递是函

24、数原型可写为: type fun(type a, int size); 也可写为 type fun(type *p, int size); 但在函数内部,a和p都能当作数组使用 调用时,对这两种形式都可用数组名或指针作为实参 建议:如果传递的是数组,用第一种形式;如果传递的是普通的指针,用第二种形式,#include using namespace std; void f(int arr, int k) cout sizeof(arr) “ “ sizeof(k) endl; void main() int a10=1,2,3,4,5,6,7,8,9,0; cout sizeof(a) end

25、l; f(a,10); ,输出: ,C+将数组名作为参数传递处理成指针的传递,即在main中,a是数组,占用了40个字节。而在函数f中,arr是一个指针,数组传递的灵活性,void sort(int p , int n) . main() int a100; . sort(a, 100); /排序整个数组 sort(a, 50); /排序数组的前50个元素 sort(a+50, 50); /排序数组的后50个元素 . ,实例,设计一函数用分治法在一个整数数组中找出最大和最小值 具体方法是: 如果数组只有一个元素,则最大最小都是他。 如果数组中只有两个元素,则大的一个就是最大数,小的就是最小数。

26、这种情况不需要递归。 否则,将数组分成两半,递归找出前一半的最大最小值和后一半的最大最小值。取两个最大值中的较大者作为最大值,两个最小值中的较小值作为最小值。,设计考虑,函数的参数是要查找的数组,传递一个数组要两个参数:数组名和数组规模 函数返回的是数组中的最大值和最小值,将它们作为指针传递的参数 查找数组的前一半就是递归调用本函数,传给他的参数是当前的数组名,数组的规模是原来的一半 查找数组的后一半也是递归调用本函数,传给它的参数是数组后一半的起始地址,规模也是原来的一半,伪代码,void minmax ( int a , int n , int *min_ptr , int *max_pt

27、r) switch (n) case 1: 最大最小都是a0; case 2: 大的得放入*max_ptr,小的放入*min_ptr; Default: 对数组a的前一半和后一般分别调用minmax; 取两个最大值中的较大者作为最大值; 取两个最小值中的较小值作为最小值 ,void minmax ( int a , int n , int *min_ptr , int *max_ptr) int min1 , max1 , min2 , max2; switch(n) case 1: *min_ptr = *max_ptr = a0; return; case 2: if (a0 a1 ) *

28、min_ptr = a0; *max_ptr= a1; else *min_ptr = a1; *max_ptr= a0; return; default: minmax( a, n/2, ,指针作为函数参数和返回值,指针作为函数参数 数组名作为函数参数 返回指针的函数 引用和引用传递 返回引用的函数,返回指针的函数,函数的返回值可以是一个指针 返回指针的函数原型: 类型 *函数名(形式参数表); 当函数的返回值是指针时,返回地址对应的变量不能是局部变量。,实例,设计一个函数从一个字符串中取出一个子串。 原型设计: 从哪一个字符串中取子串、起点和终点 返回值:字符串可以用一个指向字符的指针表示

29、,所以函数的执行结果是一个字符串,表示一个字符串可以用一个指向字符的指针 返回值指针指向的空间必须在返回后还存在。这可以用动态字符数组,char *subString(char *s, int start, int end) int len = strlen(s); if (start = len | end = len | start end) cout “起始或终止位置错“ endl; return NULL; char *sub = new charend - start + 2; strncpy(sub, s + start, end - start +1); subend - sta

30、rt +1 = 0; return sub; ,指针作为函数参数和返回值,指针作为函数参数 数组名作为函数参数 返回指针的函数 引用和引用传递 返回引用的函数,引用传递,引用传递是地址传递的另一种更简单明了的实现方法,引用的概念 函数中的引用,C+中的引用,引用的定义:给一个变量取一个别名,使一个内存单元可以通过不同的变量名来访问。 例:int i; int j是i的别名,i与j是同一个内存单元。 C+引入引用的主要目的是将引用作为函数的参数。,引用传递,引用传递是地址传递的另一种更简单明了的实现方法,引用的概念 函数中的引用,引用参数,C+引入引用的主要目的是将引用作为函数的参数。,指针参数

31、 void swap(int *m, int *n) int temp; temp=*m; *m=*n; *n=temp; 调用:swap(&x, &y),引用参数 void swap(int 调用:swap( x, y),注意:实参必须是变量,而不能是一个表达式,调用swap(x,y)时,相当于发生了变量定义 int &m = x int &n = y 即,形式参数m和实际参数x共享一块空间,形式参数n和实际参数y共享一块空间。在swap函数中交换了m和n的值,就相当于交换了x和y的值。,指针作为函数参数和返回值,指针作为函数参数 数组名作为函数参数 返回指针的函数 引用和引用传递 返回引用

32、的函数,返回引用的函数的主要用途,将函数用于赋值运算符的左边,即作为左值。 int a = 1, 3, 5, 7, 9; int /函数是aj的一个引用,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,指针数组与多级指针,指针数组 Main函数的参数 多级指针,指针数组,地址本身也是数据,他们也可以像其他数据一样组织成一个数组 一个数组,如果他的元素均为指针,则称为指针数组 一维指针数组的定义形式: 类型名 *数组名数组长度; 例如,char *String10; 定义了一个名为St

33、ring的指针数组,该数组有10个元素,数组的每个成员是一个指向字符的指针,指针数组的应用,字符串可以用一个指向字符的指针表示,一组字符串可以用一个指向字符的指针数组来表示 例:写一个函数用二分法查找某一个城市在城市表中是否出现。用递归实现 关键问题: 城市表的存储:用指向字符的指针数组 查找时的比较:用字符串比较函数,/该函数用二分查找在cityTable中查找cityName是否出现 /lh和rh表示查找范围,返回出现的位置 Int binarySearch(char *cityTable, int lh, int rh, char *cityName) int mid, result;

34、if (lh 0) return binarySearch(cityTable, lh, mid-1, cityName); else return binarySearch(cityTable, mid+1, rh,cityName); return -1; /没有找到 ,函数的应用,#include using namespace std; int binarySearch(char *cityTable, int lh, int rh, char *cityName); int main() char *string10 = “aaa“, “bbb“, “ccc“, “ddd“, “ee

35、e“, “fff“, “ggg“, “hhh“, “iii“,“jjj“; char tmp10; while (cin tmp) cout binarySearch(string, 0, 9, tmp) endl; return 0; ,指针数组与多级指针,指针数组 Main函数的参数 多级指针,main函数的形参,如需要实现:copy a b之类的功能,可以用带有参数的main函数来实现 main函数有二个形式参数: int argc, char *argv argc 参数的数目(包括命令名本身) argv 指向每个参数的指针,是一个指向字符串的指针数组,把参数传递给main(),#inc

36、lude int main(int argc, char *argv) int i; cout “argc=“ argc endl; for(i=0; iargc; +i) cout “argv“ i “=“ argvi endl; return 0; ,假设生成的执行文件myprogram.exe,把参数传递给main() 续,假设生成的执行文件myprogram.exe 在命令行输入:myprogram 输出结果:argc=1 argv0=myprogram 在命令行输入:myprogram try this 输出结果:argc=3 argv0=myprogram argv1=try ar

37、gv2=this,main函数参数实例,编写一个求任意n个正整数的平均数的程序 如果该程序对应的可执行文件名为aveg,则可以在命令行中输入 aveg 10 30 50 20 40 表示求10、30、50、20和40的平均值,对应的输出为30。,设计考虑,将这些数据作为命令行的参数 从argc得到数据的个数 从argv得到每一个数值,但注意数值是以字符串表示,要进行计算,必须把它转换成真正的数值 由于每个数据都要转换,而且这个工作很独立,所以将它设计成一个函数,字符串形式的数字转换到真正的数值,int ConvertStringToInt(char *s) int num = 0; while

38、(*s) num = num * 10 + *s - 0; +s; return num; ,计算程序,int main(int argc, char *argv) int sum = 0; for (int i = 1; i argc; +i) sum += ConvertStringToInt(argvi); cout sum / (argc - 1) endl; return 0; ,指针数组与多级指针,指针数组 Main函数的参数 多级指针,多级指针,指针指向的内容还是一个指针,称为多级指针 如有定义:char *string10; string是一个数组,数组元素可以通过指针来访问。

39、如果p是指向数组string的某一个元素,那么p指向的内容是一个指向字符的指针,因此p就是一个多级指针。string也是一个多级指针,不过是一个常指针,多级指针的定义,两级指针:类型名 *变量名; 三级指针:类型名 *变量名; 如:int *q; 表示q指向的内容是一个指向整型的指针。可以这样使用:int x=15, *p= 表示s指向的内容是一个指向字符的指针,多级指针的应用,可以用指向指针的指针访问指针数组的元素。如 #include using namespace std; int main() char *city = “aaa“, “bbb“, “ccc“, “ddd“, “eee“

40、; char *p; for (p=city; pcity+5; +p) cout *p endl; return 0; ,输出结果: aaa bbb ccc ddd eee,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,二维数组与指针,int a34;等价于定义了3个变量,指向一维数组的指针,a 是一个指针数组,它的每个元素是一个整型指针,指向每一行的第一个元素。a是一个指向一维数组的指针,指向a 的第一个元素。对a加1,事实上是跳到下一行 指向一维数组的指针可以这样定义: 类型

41、名 (*指针变量名)一维数组的元素个数; 注意:圆括号不能省略,如果省略了圆括号就变成了指针数组,等价于aij的表达式,int a35;,用指向数组的指针输出二维数组a,int (*p)4, *q; for (p = a; p a + 3; +p) /每一行 for (q = *p; q *p+4; +q) /每一列 cout *q t; cout endl; ,注意:如果输出a和a0,这两个值是相同的。但是,这两个值的含义是不同的,前者是第0行的首地址,它的类型是指向由四个元素组成的一位数组的首地址,后者是第0行第一个元素的地址,它的类型是整型指针,动态的二维数组,方法一:用一维动态数组 将

42、它按行序转换成一维数组,用动态的一维数组存储。如一个3行4列的矩阵a可以存储为12个元素的一维数组 访问i行j列的元素转换成访问一维数组的第4*i+j个元素 方法二:用指向指针的指针,可以用aij访问 用指向指针的指针指向一个一维的指针数组 指针数组中的每个元素指向矩阵的每一行的第一个元素,int main() int *a, i, j, k = 0; a = new int *3; for (i = 0; i 3; +i) ai = new int4; for (i = 0; i 3; +i) for (j = 0; j 4; +j) aij = k+; for (i = 0; i 3; +

43、i) cout endl; for (j = 0; j 4; +j) cout aij t; for (i = 0; i 3; +i) delete ai; delete a; return 0; ,第7章 间接访问指针,指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针 指向多维数组的指针 指向函数的指针,函数的指针和指向函数的指针变量,定义:返回类型 (*指针变量名)( ) ; 使用 : 赋值 eg. int isdigit(int n, int k); . int (*p)(int, int ); p=isdigit; 引用:a=isdi

44、git(n,k); a=(*p)(n,k); 或 a=p(n,k),函数的指针:指向函数代码的起始地址,函数的指针的用途,菜单选择的实现 作为函数的参数,函数指针的应用,用函数指针的数组实现菜单选择 例如,在一个工资管理系统中有如下功能: 1。添加员工; 2。删除员工; 3。修改员工信息; 4。打印工资单; 5。打印汇总表; 6。退出。 在设计中,一般把每个功能设计成一个函数。如添加员工的函数为add,删除员工的函数为delete,修改员工信息的函数为modify,打印工资单的函数为printSalary,打印汇总表函数为printReport。主程序是一个循环,显示所有功能和它的编号,请用户

45、输入编号,根据编号调用相应的函数。,int main() int select; while(1) cout select; switch(select) case 0: return 0; case 1: add(); break; case 2: erase(); break; case 3: modify(); break; case 4: printSalary(); break; case 5: printReport(); break; default: cout “input errorn“; ,利用指向函数的指针,int main() int select; void (*fu

46、nc6)() = NULL, add, erase, modify, printSalary, printReport; while(1) cout select; if (select = 0) return 0; if (select 5) cout “input errorn“; else funcselect(); ,函数指针的应用,把函数指针作为函数的参数 例:设计一个通用的快速排序函数,可以排序任何类型的数据 关键问题 如何表示要排序的数据:将快速排序设计成一个函数模板,将待排序的数据类型设计成模板参数 不同类型的数据有不同的比较方式:向排序函数传递一个比较函数来解决。,templ

47、ate void quicksort(T data, int low, int high, int (*comp)(T, T) int mid; if (low = high) return; mid = divide(data, low, high, comp); quicksort( data, low, mid-1, comp); quicksort( data, mid+1, high, comp); ,template int divide(T data, int low, int high, int (*comp)(T, T) T k = datalow; do while (low 0) -high; if (low high) datalow = datahigh; +low; while (low high ,通用快速排序的应用,如果需要排序一组字符串,待排序的一组字符串保存在数组a中。a的定义如下: char *a=“aaa“, “nnn“, “rrr“, “fff“, “sss“, “ggg“, “ddd“; 调用 quicksort(a, 0, 6, strcmp);,通用快速排序的应用,如果

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

当前位置:首页 > 其他


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