第6章数组、指针与字符串.ppt

上传人:本田雅阁 文档编号:3431736 上传时间:2019-08-24 格式:PPT 页数:112 大小:758.04KB
返回 下载 相关 举报
第6章数组、指针与字符串.ppt_第1页
第1页 / 共112页
第6章数组、指针与字符串.ppt_第2页
第2页 / 共112页
第6章数组、指针与字符串.ppt_第3页
第3页 / 共112页
第6章数组、指针与字符串.ppt_第4页
第4页 / 共112页
第6章数组、指针与字符串.ppt_第5页
第5页 / 共112页
点击查看更多>>
资源描述

《第6章数组、指针与字符串.ppt》由会员分享,可在线阅读,更多相关《第6章数组、指针与字符串.ppt(112页珍藏版)》请在三一文库上搜索。

1、第六章 数组 指针与字符串,C+语言程序设计,2,本章主要内容,数组 指针 动态存储分配 指针与数组 指针与函数 vector的基本用法 字符串 小结,3,数组的概念,数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。 数组属于构造类型。,数 组,4,一维数组的声明与使用,一维数组的声明 类型说明符 数组名 常量表达式 ; 例如:int a10; 表示 a 为整型数组,有10个元素:a0.a9,说 明 (1)数组在内存中是连续存放的,必须先声明,后使用。 (2) 数组名应该是一个合法的标识符,它表示数组在内存 的起始地址。 (3)第一个元素的下标是 0。 (4)

2、具有相同的名字和类型。,数 组,5,例6. 1一维数组的声明与引用,#include using namespace std; int main() int a10, b10; for(int i = 0; i 10; i+) ai = i * 2 - 1; b10 - i - 1 = ai; for(int i = 0; i 10; i+) cout “a“ i “ = “ ai “ “; cout “b“ i “ = “ bi endl; return 0; ,6,一维数组的存储顺序,数组元素在内存中顺次存放,它们的地址是连续的。 例如:具有10个元素的数组 a,在内存中的存放次序如下:,

3、数组名字是数组首元素的内存地址。 数组名是一个常量,不能被赋值。,数 组,7,一维数组的初始化,数组的初始化就是在定义数组时对部分或全部元素赋初值。 例如:int a10=0,1,2,3,4,5,6,7,8,9; int a10=0,1,2,3,4; / 后5个元素值为0 在对全部数组元素赋初值时,可以不指定数组长度。 int a5=1,2,3,4,5; int a=1,2,3,4,5; /两个语句等价 int a5=1,2,3,4,5,6;/错误,初始化给出的元素个数不能超过数组的长度,例1: 从键盘输入10个整数,将它们逆序输出。 #include using namespace std;

4、 int main() int i,a10; for (i=0;iai; for (i=9;i=0;i-) coutai“ “; coutendl; return 0; ,0 1 2 3 4 5 6 7 8 9,9,8,7,6,5,4,3,2,1,0,例2:输出数组并对数组元素求和,#define SIZE 10 #include int main( ) int nSIZE = 12, 34, 55, 71, 1, 65, 423, 19, 540, 10 ; int i , sum = 0; for ( i = 0; i = SIZE - 1; i+ ) cout “n“ i “ = “ n

5、 i endl; sum += n i ; cout “The summary is: “ sum endl; return 0; ,程序执行结果:,n0 = 12 n1 = 34 n2 = 55 n3 = 71 n4 = 1 n5 = 65 n6 = 423 n7 = 19 n8 = 540 n9 = 10 The summary is: 1230,11,二维数组的声明及引用,数据类型 标识符常量表达式1常量表达式2 ; 例: int a53; 表示a为整型二维数组,其中第一维有5个下标(04),第二维有3个下标(02),数组的元素个数为15,可以用于存放5行3列的整型数据表格。,数 组,1

6、2,存储顺序 按行存放,上例中数组a的存储顺序为:,二维数组的声明 类型说明符 数组名常量表达式常量表达式 例如:float a34;,引用:下标可以是整型表达式 例: a23、a3-12*2-1 但不要写成a2,3,下标不要越界,二维数组的声明及引用,数 组,13,将所有数据写在一个 内,按顺序赋值 int a34=1,2,3,4,5,6,7,8,9,10,11,12; 分行给二维数组赋初值 int a34=1,2,3,4,5,6,7,8,9,10,11,12; 可以对部分元素赋初值 int a34=1,0,2,0,0,3;,二维数组的初始化,赋初值省略第一维的大小 int a 4=1,2,

7、3,4,5,6,7,8,9,10,11,12; 等价于: int a34=1,2,3,4,5,6,7,8,9,10,11,12; 在定义时也可以只对部分元素赋初值而省略第一维的大小,但应分行赋初值。如 int a 4=0,1, ,1,0,1; 这样的写法,能通知编译系统,数组共有3行。 数组各元素为:,例3: 将一个3*4矩阵转置后输出。例如 矩阵 转置后成为矩阵 #include using namespace std; int main() int i,j, b43; int a34=1,2,3,4,1,2,3,4,1,2,3,4; cout“Before converting“endl;

8、,for (i=0;i3;i+) for (j=0;j4;j+) coutaij“ ”; coutendl; for (i=0;i3;i+) for (j=0;j4;j+) bji=aij; cout“After converting“endl; for (i=0;i4;i+) for (j=0;j3;j+) coutbij “ ”; coutendl; return 0; ,17,数组作为函数参数,数组元素作函数实参,与单个变量一样。 数组名作函数参数,形、实参数都应是数组名,类型要一样,传送的是数组首地址。对形参数组的改变会直接影响到实参数组。,数 组,18,例6-2 使用数组名作为函数参

9、数,主函数中初始化一个矩阵并将每个元素都输出,然后调用子函数,分别计算每一行的元素之和,将和直接存放在每行的第一个元素中,返回主函数之后输出各行元素的和。,数 组,#include using namespace std; void rowSum(int a4, int nRow) /计算二维数组a每行元素值的和,nRow是行数 for (int i = 0; i nRow; i+) for(int j = 1; j 4; j+) ai0 += aij; int main() int table34 = 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6; /声明并初始化数组

10、,19,/输出数组元素 for (int i = 0; i 3; i+) for (int j = 0; j 4; j+) cout tableij “ “; cout endl; /调用子函数,计算各行和,输出计算结果 rowSum(table, 3); for (int i = 0; i 3; i+) cout “Sum of row “ i “ is “ tablei0 endl; return 0; ,20,运行结果: 1 2 3 4 2 3 4 5 3 4 5 6 Sum of row 0 is 10 Sum of row 1 is 14 Sum of row 2 is 18,21,

11、22,对象数组,声明: 类名 数组名元素个数; 访问方法: 通过下标访问 数组名下标.成员名,数 组,23,对象数组初始化,数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。 通过初始化列表赋值。 例: Point a2=Point(1,2),Point(3,4); 如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(调用缺省构造函数)。,数 组,24,数组元素所属类的构造函数,不声明构造函数,则采用缺省构造函数。 当数组中每一个对象被删除时,系统都要调用一次析构函数。 操作对象数组的 元素 一般形式 数组名下标.公有成员函数名(实参列表);,数 组,25,例6-3

12、对象数组应用举例,/Point.h #ifndef _POINT_H #define _POINT_H class Point /类的定义 public: /外部接口 Point(); Point(int x, int y); Point(); void move(int newX,int newY); int getX() const return x; int getY() const return y; static void showCount(); /静态函数成员 private: /私有数据成员 int x, y; ; #endif /_POINT_H,数 组,/Point.cpp

13、 #include #include “Point.h“ using namespace std; Point:Point() x = y = 0; cout “Default Constructor called.“ endl; Point:Point(int x, int y) : x(x), y(y) cout “Constructor called.“ endl; Point:Point() cout “Destructor called.“ endl; void Point:move(int newX,int newY) cout “Moving the point to (“ ne

14、wX “, “ newY “)“ endl; x = newX; y = newY; ,26,/6-3.cpp #include “Point.h“ #include using namespace std; int main() cout “Entering main.“ endl; Point a2; /对象数组 for(int i = 0; i 2; i+) ai.move(i + 10, i + 20); cout “Exiting main.“ endl; return 0; ,27,运行结果: Entering main. Default Constructor called. D

15、efault Constructor called. Moving the point to (10, 20) Moving the point to (11, 21) Exiting main. Destructor called. Destructor called.,28,29,关于内存地址,内存空间的访问方式 通过变量名访问 通过地址访问 地址运算符: 则&var 表示变量var在内存中的起始地址,30,声明:数据类型 *变量名; 例:int i; int *ptr = 指向整型变量的指针,概念 指针:内存地址,用于 间接访问内存单元 指针变量: 用于存放地址的变量,引用 例1:i =

16、 3; 例2:*ptr = 3;,指 针,指针变量的概念,31,语法形式 数据类型 *指针名初始地址; 例:int a,*pa = / pa,pb,可以进行赋值运算,指 针,指针变量的初始化,32,指针变量的赋值运算,指针名=地址 “地址”中存放的数据类型与指针类型必须相符。 向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。 #define NULL 0 int *p=NULL; /把指针变量初始化为空指针 允许声明指向 void 类型的指针。该指针可以被赋予任何类型对象的地址。 例: void *general; int i=5; general=,33

17、,例6-5 指针的声明、赋值与使用,#include using namespace std; int main() int i; /定义int型数i int *p = ,指 针,程序运行的结果是: i = 10 *p = 10,34,35,例6-6 void类型指针的使用,#include using namespace std; int main() /!void voidObject;错,不能声明void类型的变量 void *pv; /对,可以声明void类型的指针 int i = 5; pv = ,36,指向常量的指针,不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外

18、的对象。 例 int a; const int *p1 = /编译时出错,不能通过p1改变所指的对象,指 针,37,指针类型的常量,若声明指针常量,则指针本身的值不能被改变。 例: int a,b; int * const p2 = /错误,p2是指针常量,值不能改变,指 针,38,指针变量的算术运算,指针与整数的加减运算 指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。 例:p + n /指针p当前位置后方第n个数的地址 *(p + n)等价于 pn /p当前位置后方第n个数的内容 “指针+,指针- -”运算 指向下一个或前一个数据。 例如:y=*px+ 相当于 y

19、=*(px+) (*和+优先级相同,自右向左运算),指 针,pa,39,pb-1,pb,pb+1,pb+2,*(pb-1)或pb-1,*pb或pb0,*(pb+1)或pb1,*(pb+2)或pb2,long *pb,40,41,关系运算包括:、=、=、=、!= 指向相同类型数据的指针之间可以进行各种关系运算。 指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。 指针可以和零之间进行等于或不等于的关系运算。例如:p=0或p!=0 赋值运算 向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。,指针变量的关系运算,指 针,42,指向数组元素的

20、指针,声明与赋值 例:int a10, *pa; pa= 通过指针引用数组元素 经过上述声明及赋值后: *pa就是a0,*(pa+1)就是a1,. ,*(pa+i)就是ai. ai, *(pa+i), *(a+i), pai都是等效的。 不能写 a+,因为a是数组首地址是常量。,指 针,43,例6-7,设有一个int型数组a,有10个元素。用三种方法输出各元素: 使用数组名和下标 使用数组名和指针运算 使用指针变量,指 针,#include using namespace std; int main() int a10 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ; for

21、(int i = 0; i 10; i+) cout ai “ “; cout endl; return 0; ,使用数组名和下标,44,#include using namespace std; int main() int a10 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ; for (int i = 0; i 10; i+) cout *(a+i) “ “; cout endl; return 0; ,使用数组名指针运算,45,使用指针变量,#include using namespace std; int main() int a10 = 1, 2, 3, 4, 5

22、, 6, 7, 8, 9, 0 ; for (int *p = a; p (a + 10); p+) cout *p “ “; cout endl; return 0; ,46,47,指针数组,数组的元素是指针型 一维指针数组的语法形式: 数据类型 *数组名下标表达式; 例: int *array10; Point *pa2; 由pa0,pa1两个指针组成,指 针,48,例6-8 利用指针数组存放单位矩阵,#include using namespace std; int main() int line1 = 1, 0, 0 ; /矩阵的第一行 int line2 = 0, 1, 0 ; /矩

23、阵的第二行 int line3 = 0, 0, 1 ; /矩阵的第三行 /定义整型指针数组并初始化 int *pLine3 = line1, line2, line3 ;,cout “Matrix test:“ endl; /输出单位矩阵 for (int i = 0; i 3; i+) for (int j = 0; j 3; j+) cout *(pLinei+j) “ “; cout endl; return 0; ,输出结果为: Matrix test: 1,0,0 0,1,0 0,0,1,49,50,以指针作为函数参数,指针做函数的参数,以地址方式传递数据,可以用来返回函数处理结果。

24、 实参是数组名时形参可以是指针。 例: void sf(float x, int *i),指针与函数,51,例:读入三个浮点数,将整数部分和小数部分分别输出,#include using namespace std; void splitFloat(float x, int *intPart, float *fracPart) /取x的整数部分 *intPart = static_cast(x); /取x的小数部分 *fracPart = x - *intPart; ,指针与函数,int main() cout x; splitFloat(x, ,52,运行结果: Enter 3 floati

25、ng point numbers 4.7 Integer Part = 4 Fraction Part = 0.7 8.913 Integer Part = 8 Fraction Part = 0.913 -4.7518 Integer Part = -4 Fraction Part = -0.7518,53,54,例: 输出数组元素的内容和地址,#include #include using namespace std; void arrayPtr(long *p, int n) /形参是指针 cout “In func, address of array is “ p endl; cout

26、“Accessing array using pointers“ endl; for (int i = 0; i n; i+) cout “Address for index “ i “ is “ p + i; cout “ Value is “ *(p + i) endl; ,指针与函数,int main() long list5=50, 60, 70, 80, 90; cout “In main, address of array is “ list endl; cout endl; arrayPtr(list,5); /实参是数组名 return 0; ,55,运行结果: In main

27、, address of array is 0012FF50 In func, address of array is 0012FF50 Accessing array using pointers Address for index 0 is 0012FF50 Value is 50 Address for index 1 is 0012FF54 Value is 60 Address for index 2 is 0012FF58 Value is 70 Address for index 3 is 0012FF5C Value is 80 Address for index 4 is 0

28、012FF60 Value is 90,56,指针型函数,当函数的返回值是指针类型时,该函数就是指针型函数。 语法形式: 数据类型 *函数名(形参表) 函数体 例如: float * fun(int a) ,58,对象指针的一般概念,声明形式 类名 *对象指针名; 通过指针访问对象成员 对象指针名-成员名 等价于(*对象指针名).成员名 ptr-getx() 相当于 (*ptr).getx(); 例:point a, *p; p=,指 针,59,this指针,this指针,它是一个特殊的对象指针,指向对象自身。this指针被隐含地用来访问对象的数据成员和成员函数。 例如:Point类的getX

29、函数中的语句: return x; 相当于: return this-x;,指 针,60,指向类的非静态成员的指针,通过指向成员的指针只能访问公有成员 声明指向成员的指针 声明指向公有数据成员的指针 类型说明符 类名:*指针名; 声明指向公有函数成员的指针 类型说明符 (类名:*指针名)(参数表); 例如:point a;/普通对象a int point:*p1; /指向point类数据成员的指针p1 void (point:*p2)(void); /指向point类成员函数的指针p2,指 针,61,指向类的非静态成员的指针,指向数据成员的指针 赋值形式: 指针名 = &类名:数据成员名; 通

30、过对象名(或对象指针)与成员指针结合来访问数据成员 对象名.*类成员指针名 或: 对象指针名-*类成员指针名,指 针,62,指向类的非静态成员的指针,指向函数成员的指针 赋值形式: 指针名=&类名:函数成员名; 通过对象名(或对象指针)与成员指针结合来访问函数成员 (对象名.*类成员指针名)(参数表) 或: (对象指针名-*类成员指针名)(参数表),指 针,63,指向类的非静态成员的指针,例6-13 访问对象的公有成员函数的不同方式 int main() Point a(4,5); /声明对象a Point *p1 = ,指 针,64,指向类的静态成员的指针,对类的静态成员的访问不依赖于对象

31、可以用普通的指针来指向和访问静态成员 例6-14 通过指针访问类的静态数据成员 例6-15 通过指针访问类的静态函数成员,指 针,65,动态申请内存操作符 new,new 类型名T(初始化参数列表) 功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。 结果值:成功:T类型的指针,指向新分配的内存;失败:抛出异常。,动态存储分配,66,释放内存操作符delete,delete 指针p 功能:释放指针p所指向的内存。p必须是new操作的返回值。,动态存储分配,67,例6-16 动态创建对象举例,#include using namespace std; class Po

32、int public: Point() : x(0), y(0) cout“Default Constructor called.“endl; Point(int x, int y) : x(x), y(y) cout “Constructor called.“endl; Point() cout“Destructor called.“endl; int getX() const return x; int getY() const return y; void move(int newX, int newY) x = newX; y = newY; private: int x, y; ;,

33、动态存储分配,int main() cout “Step one: “ endl; Point *ptr1 = new Point;/调用缺省构造函数 delete ptr1; /删除对象,自动调用析构函数 cout “Step two: “ endl; ptr1 = new Point(1,2); delete ptr1; return 0; ,运行结果: Step One: Default Constructor called. Destructor called. Step Two: Constructor called. Destructor called.,68,申请和释放动态数组,

34、分配:new 类型名T 数组长度 数组长度可以是任何表达式,在运行时计算 释放:delete 数组名p 释放指针p所指向的数组。p必须是用new分配得到的数组首地址。,69,70,例6-17动态创建对象数组举例,#include using namespace std; class Point /类的声明同例6-16,略 ; int main() Point *ptr = new Point2; /创建对象数组 ptr0.move(5, 10);/通过指针访问数组元素的成员 ptr1.move(15, 20);/通过指针访问数组元素的成员 cout “Deleting.“ endl; dele

35、te ptr; /删除整个对象数组 return 0; ,动态存储分配,运行结果: Default Constructor called. Default Constructor called. Deleting. Destructor called. Destructor called.,71,将动态数组封装成类,更加简洁,便于管理 建立和删除数组的过程比较繁琐 封装成类后更加简洁,便于管理 可以在访问数组元素前检查下标是否越界 用assert来检查,assert只在调试时生效,72,例6-18动态数组类,#include #include using namespace std; clas

36、s Point /类的声明同例6-16 ; class ArrayOfPoints /动态数组类 public: ArrayOfPoints(int size) : size(size) points = new Pointsize; ArrayOfPoints() cout = 0 ,73,int main() int count; cout count; ArrayOfPoints points(count); /创建对象数组 /通过访问数组元素的成员 points.element(0).move(5, 0); /通过类访问数组元素的成员 points.element(1).move(15

37、, 20); return 0; ,74,运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Deleting. Destructor called. Destructor called.,75,76,动态创建多维数组,new 类型名T第1维长度第2维长度; 如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,是一个T类型的数组,数组元素的个数为除最左边一维外各维下标表达式的乘积。例如: char (*fp)3; fp = new ch

38、ar23;,动态存储分配,char (*fp)3;,fp,fp+1,77,78,例6-19动态创建多维数组,#include using namespace std; int main() float (*cp)98 = new float898; for (int i = 0; i (i * 100 + j * 10 + k);,动态存储分配,for (int i = 0; i 8; i+) for (int j = 0; j 9; j+) for (int k = 0; k 8; k+) /将指针cp作为数组名使用,通过数组名和下标访问数组元素 cout cpijk “ “; cout e

39、ndl; cout endl; delete cp; return 0; ,79,用vector创建动态数组,为什么需要vector? 将动态数组封装,自动创建和删除 数组下标越界检查 例6-18中封装的ArrayOfPoints也提供了类似功能,但只适用于一种类型的数组 vector动态数组对象的定义 vector 数组对象名(数组长度); 例:vector arr(5) 建立大小为5的int数组,80,vector动态数组对象,vector数组对象的使用,对数组元素的引用 与普通数组具有相同形式: 数组对象名 下标表达式 但vector数组对象名不表示数组首地址 获得数组长度 用size函

40、数 数组对象名.size(),81,vector动态数组对象,例6-20 vector应用举例,#include #include using namespace std; /计算数组arr中元素的平均值 double average(const vector ,82,vector动态数组对象,int main() unsigned n; cout n; vector arr(n); /创建数组对象 cout arri; cout “Average = “ average(arr) endl; return 0; ,83,84,浅拷贝与深拷贝,浅拷贝 实现对象间数据元素的一一对应复制。 深拷贝

41、 当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指的对象进行复制。,浅拷贝与深拷贝,85,例6-21对象的浅拷贝,#include #include using namespace std; class Point /类的声明同例6-16 / ; class ArrayOfPoints /类的声明同例6-18 / ;,浅拷贝与深拷贝,int main() int count; cout count; ArrayOfPoints pointsArray1(count); /创建对象数组 pointsArray1.element(0).move(5,10); points

42、Array1.element(1).move(15,20); ArrayOfPoints pointsArray2 = pointsArray1; /创建副本 cout “Copy of pointsArray1:“ endl; cout “Point_0 of array2: “ pointsArray2.element(0).getX() “, “ pointsArray2.element(0).getY() endl; cout “Point_1 of array2: “ pointsArray2.element(1).getX() “, “ pointsArray2.element(1

43、).getY() endl;,86,pointsArray1.element(0).move(25, 30); pointsArray1.element(1).move(35, 40); cout “After the moving of pointsArray1:“ endl; cout “Point_0 of array2: “ pointsArray2.element(0).getX() “, “ pointsArray2.element(0).getY() endl; cout “Point_1 of array2: “ pointsArray2.element(1).getX() “

44、, “ pointsArray2.element(1).getY() endl; return 0; ,87,运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Copy of pointsArray1: Point_0 of array2: 5, 10 Point_1 of array2: 15, 20 After the moving of pointsArray1: Point_0 of array2: 25, 30 Point_1 of a

45、rray2: 35, 40 Deleting. Destructor called. Destructor called. Deleting. 接下来程序出现异常,也就是运行错误。,88,拷贝前,拷贝后,89,90,例6-22对象的深拷贝,#include #include using namespace std; class Point /类的声明同例6-16 ; class ArrayOfPoints public: ArrayOfPoints(const ArrayOfPoints,浅拷贝与深拷贝,ArrayOfPoints:ArrayOfPoints(const ArrayOfPoin

46、ts int main() /同例6-20 ,91,程序的运行结果如下: Please enter the number of points:2 Default Constructor called. Default Constructor called. Default Constructor called. Default Constructor called. Copy of pointsArray1: Point_0 of array2: 5, 10 Point_1 of array2: 15, 20 After the moving of pointsArray1: Point_0

47、of array2: 5, 10 Point_1 of array2: 15, 20 Deleting. Destructor called. Destructor called. Deleting. Destructor called. Destructor called.,92,拷贝前,拷贝后,93,用字符数组存储和处理字符串,字符串常量(例:“program“) 各字符连续、顺序存放,每个字符占一个字节,以0结尾,相当于一个隐含创建的字符常量数组 “program”出现在表达式中,表示这一char数组的首地址 首地址可以赋给char常量指针: const char *STRING1 = “program

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

当前位置:首页 > 其他


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