四章数组与指针ppt课件-PPT精品文档_图文

C/C++
程序设计

C/C++程序设计
胡立坤

GuangXi University

1

C/C++
程序设计
GuangXi University

第4章数组与指针及其应用
数组用于保存大量同类型的相关 数据,如矩阵运算,表格数据等。
4.1 一维数组 4.2 二维数组 4.3 字符串 4.4 指针和数组 4.5动态数组 4.6 程序举例
2

C/C++
程序设计

4.1一维数组

4.1.1 引例

例4.1求N个学生的平均成绩,并统计高于平均分的人数 。

用以前所学知识实现:
int k=0;float s,ave,sum=0; for(int i=0;i<100;i++) { cin>>s;
sum=sum+s; } ave=sum/100; for(i=0;i<100;i++) { cin>>s;
if(s>ave) k++; }

用数组来实现:

int k=0;float s[100],ave,sum=0;

for(i=0;i<100;i++)

{ cin>>s[i];

采用随机数函数 s[i]=rand()%101

sum=sum+s[i]; }

ave=sum/100;

for(i=0;i<100;i++)

if(s[i]>ave)k++;

数组:一组数据类型相同的元素按一定顺序存放,构成的数据集合。

GuangXi University

3

4.1一维数组
C/C++
程序设计
4.1.2一维数组的定义、存储和初始化
(1) 数组的形式 数据类型 数组名[整型常量表达式];
如: int s[5];
s[0] s[1] s[2] s[3] s[4] ? 下标从0开始 ? 数组名是常量,表示数组在内存中的首地址。 ? 数组长度应该为整型常量表达式,不能是变量。如:

正确: ? const int s=10;
int a[s]; ? float f[5];

错误:
? int s=10;
int a[s];
? float b[3.4]

GuangXi University

4

C/C++
程序设计

4.1一维数组

(2)数组的初始化

a. 给所有元素赋初值。

花括号

如:int a[5]={0,2,4,6,8}; 或 int a[ ]={0,2,4,6,8};

b. 给部分元素赋初值。如:int a[10]={1,3,5,7,9};

花括号内列出的值赋给前面的若干个元素,其余元素自动赋0。

以下的语句均是错误:

× ×

int a[10]; a={1,3,5,7,9};
//数组名是个地址常量,不能被赋值。
int a[10]; a[10]={1,3,5,7,9}; ×
//a[10]不是数组中的元素,并且不能用花括号为一个元素赋 多个值。

int c[3]={1,2, 3,4};

GuangXi/U/常nive量rsit个y 数超过数组定义的长度。

5

C/C++
程序设计

4.1一维数组

说明: ? 数组大小最好用宏来定义,以适应未来可能的变化

– #define SIZE 10 int a[SIZE];
? 对数组每个元素的使用与普通变量无异,可以快速地随机 访问
? 可以用任意表达式作为下标,动态决定访问哪个元素
for (i=0; i<SIZE; i++) a[i] = 2 * i;
? 下标越界是大忌!
– 使用大于最大下标的下标,将访问数组以外的空间。那里的数据 是未知的,可能带来严重后果
? sizeof可以用来获得数组大小 ? 一旦定义,不能改变大小

GuangXi University

6

C/C++
程序设计

4.1一维数组

4.1.3数组元素的引用和基本操作

(1) 数组元素的引用 形式:数组名[下标]----相当于一个普通变量

如有: int a[10]={1,2,3,4,5,6,7,8,9,10},b[10],i(2);

则:
? a[3]=a[0]+a[i]; ? cout<<a[2+i]; ? cout<<a[a[3]];

// a[3]=1+3=4 //输出a[4]元素的值 // a[a[3]]= a[4]=5

? cout<<a[10]; ? cout<<a; ? b=a;

//数组下标越界 //对数组一般不能作为一个整体进行操作

GuangXi University

7

C/C++
程序设计
(2)基本操作

4.1一维数组

假设有定义:int a[N]; N是已定义过的符号常量。 ? 数组元素的输入和输出 ----for(j=0; j<N; j++) cin>>a[j]; ----for(j=0; j<N; j++) cout<<a[j]; ----for (i=0;i<10;i++) scanf("%d",&a[i]); ----for (i=0;i<10;i++) printf("%d",a[i]); ? 通过随机函数rand()产生0~100的N个数据 ----for ( i = 0; i<N;i++) a[i] = rand()%101; ? 数组元素的求和 ----for(sum=0 , j=0; j<N; j++) sum+=a[j];

GuangXi University

8

4.1一维数组
C/C++
程序设计
? 求数组中的最大元素

----max=a[0]; //假设第一个元素值最大

for(j=1; j<N; j++) if(a[j]>max)max=a[j];

求最大元素下标

----imax=0;

//imax代表最大元素下标

for (j=1;j<N;j++) if(a[j]>a[imax])imax=j;

? 将最大元素放于某一特定位置(如放在最前头)

----imax=0;

for(j=1;j<N;j++) if(a[j]>a[imax])imax=j;

if(imax!=0) {t=a[0];a[0]=a[imax];a[imax]=t;}

GuangXi University

9

C/C++
程序设计
4.1.4 数组排序

4.1一维数组

排序是将一组数按递增或递减的次序排列,如按学 生的成绩、球赛积分等排序。常用的算法有:

? 选择法 (√) ? 冒泡法 (√) ? 插入法 ? 快速排序法

…...

GuangXi University

10

4.1一维数组
C/C++
程序设计
(1) 选择法排序----基本思想: (a) 从n个数的序列中选出最小的数(递增),与第1个数交换位置; (b) 除第1个数外,其余n-1个数再按(1)的方法选出次小的数,与第
2个数交换位置; (c) 重复(1)n-1遍,最后构成递增序列。 例4.3对存放在数组中的6个数,用选择法按递增排序。

下标 0 1 2 3 4
GuangXi University

for( i= 0;i<5;i++)

1~5

{ min= i;

2~5

for(j=i+1;j<6;j++)

3~5

if(a[j]<a[min])min= j;

4~5

if(i!=min)

5

{ temp=a[i]; a[i]= a[min];

a[min]=temp; }

}

11

4.1一维数组
C/C++
程序设计
(2) 冒泡法排序----基本思想:

(a)从第一个元素开始,对数组中两两相邻的元素比较,将值较

小的元素放在前面,值较大的元素放在后面,一轮比较完毕,

最大的数存放在a[N-1]中;

(b) 然后对a[0]到a[N-2]的N-1个数进行同(a)的操作,次最大数放

入a[N-2]元素内,完成第二趟排序;依次类推,进行N-1趟排序

后,所有数均有序。

for(i=0;i<5;i++)

例4.4用冒泡排序法实现例4.3

K=5

K=4

K=3 K=2

8

3

33

3

4

44

4

8

77

for(j=1;j< 6-i ;j++) if(a[j-1]>a[j] ) {temp=a[j-1]; a[j-1]=a[j]; a[j]=temp;

9

7

88

}

7

9

9

9 思考:当数据未交换,说明数组

GuangXi University

已有序 ,如何结束排序?

12

C/C++
程序设计

4.2二维数组

4.2.1 二维数组的定义和初始化 (1)数组的定义
形式:数据类型 数组名[常量表达式1][常量表达式2]; 如:float a[2][3];
a[0][0] a[0][1] a[0][2]

a[1][0] a[1][1] a[1][2] 以“先行后列”的规则连续存放:

a a [ 0 ] [ 0 ] a [ 0 ] [ 1 ] a [ 0 ] [ 2 ] a [ 1 ] [ 0 ] a [ 1 ] [ 1 ] a [ 1 ] [ 2 ]

序号:

1 0 0 0 H 1 0 0 4 H 1 0 0 8 H 1 0 0 C H 1 0 1 0 H 1 0 1 4 H

0

1

2

3

4

5

序号=当前行号*每行列数+当前列号

GuangXi University

13

4.2二维数组
C/C++
程序设计
(2)数组的初始化
(a)按在内存排列顺序对所有元素赋初值。
int a[2][3]={1,2,3,4,5,6}; 或 int a[][3]={1,2,3,4,5,6};

(b)按行给所有元素赋初值,每一行的数据放于一个花括号内。

int a[2][3]={{1,2,3},{4,5,6}};
(c)按行给部分元素赋初值,省略的元素初值此时自动为0。

int b[3][4]={{1,2},{0,3,4},{0,0,5}};

对应的数组b为: (d)按行赋初值也可省略第一维的长度。

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

GuangXi University

对应的数组c为:

??1 2 0 0 ?? b ? ?0 3 4 0?
?? 0 0 5 0 ??
?? 1 0 0 ?? c ? ?0 0 0?
?? 2 0 0 ?? 14

4.2二维数组
C/C++
程序设计
4.2.2 二维数组的基本操作

(1)数组的输入、输出

例4.5输入两个矩阵A、B的值,求C=A+B 。

A?????132

5 13

76????

B?????64 1831106????

分析:(1)A、B矩阵相加,其实质是将两矩阵的对应元素相加 。 相加的条件是有相同的行、列数。
(2)输入可以通过空格、Tab符和回车符控制;输出内循 环不换行,出了内循环输出endl换行。

GuangXi University

15

4.2二维数组
C/C++
程序设计
#include "iostream.h" #include "iomanip.h" void main() { int a[2][3],b[2][3],c[2][3],i,j;
for ( i = 0; i<2;i++) for( j=0; j<3; j++) cin>>a[i][j];
for ( i = 0; i<2; i++) for( j = 0; j<3; j++) cin>>b[i][j];

for ( i = 0; i<2; i++) //A+B矩阵,每个对应元素相加

for( j =0; j<3; j++)

c[i][j]=a[i][j]+b[i][j];

for ( i = 0; i<2; i++)

{ for( j=0; j<3; j++)

cout<<setw(4)<<c[i][j];

cout<<endl;

}

} GuangXi University

16

C/C++
程序设计

4.2二维数组

(2)求二维数组中最大(或最小)元素及下标

例4.6对3×3方阵,求最大元素及下标。

与一维数组求最大值的方式相同

max=a[0][0]; imax=0; jmax=0; for ( i = 0; i<3; i++)
for( j=0; j<3; j++) if( a[i][j]>max) { max=a[i][j]; imax=i; jmax=j;}

GuangXi University

17

C/C++
程序设计

4.2二维数组

(3)矩阵转置:将矩阵以主对角线为轴线,将元素的行和列

位置调换。

如对3×3方阵转置

123

14 7

a= 4 5 6

b= 2 5 8

789

36 9

for ( i = 0; i<3; i++)

for( j=0; j<i; j++)

{ t=a[i][j];

a[i][j]=a[j][i];

a[j][i]=t;

GuangXi University

}

18

C/C++
程序设计
4. 矩阵相乘

4.2二维数组

例4.7求两个矩阵a[M][N]和b[N][P]的乘积 c 。

设矩阵A、B为:

??1 4 7 10?? B ? ?2 5 8 11?
??3 6 9 12??3?4

则矩阵C为:

C??????34

? ?

? ?

??????2?4

n?1

? 即矩阵C的第i行第j列元素可通过右边公式求得: cij ? aikbkj

c00元素的实现:

k?0

s=0;

for(k=0; k<3; k++) s+=a[0][k]*b[k][0];

c[0][0]=s;

GuangXi University

19

C/C++
程序设计

4.2二维数组

#include "iostream.h"

#define M 2

#define N 3

#define P 4

void main()

{

int a[M][N]={{3,5,7},{4,6,8}},b[N][P]={{1,4,7,10},{2,5,8,11},{3,6,9,12}};

int c[M][P],i, j, k, s;

for(i=0; i<M; i++)

for(j=0; j<P; j++)

{ s=0;

// 求一个元素的值

for(k=0; k<N; k++) s+=a[i][k]*b[k][j];

c[i][j] = s;

}

for(i=0;i<M;i++)

{ for(j=0;j<P;j++) cout<<c[i][j]<<" ";

cout<<endl;

}

}

GuangXi University

20

C/C++
程序设计

4.3字符串

字符串常量: "ab123" a b 1 2 3 \0 系统自动添加 '\0'(结束标志符)
处理字符串的方法有: 字符数组、CString(string)类和字符指针。

本节只介绍前两种方法,后一种方法我们将在下一节介绍。

GuangXi University

21

C/C++
程序设计
4.3.1 字符数组

4.3字符串

(1)字符数组

char s[6];----既可以存放若干个字符,也可以存放一个

字符串。

若干个字符

abcd

字符数组

字符串

a b c d \0

char s[2][8];----可以存放一组相关的字符串,按要处理

字符串中最大长度来定义列数。

s[i][0]

s[i][7]

s[0] C O B O L \0

s[1] F O R T R A N \0

GuangXi University

22

C/C++
程序设计
(2)字符数组的初始化 (a) 逐个字符赋初值

4.3字符串

char s[10] = {'I', ' ', 'a', 'm', ' ', 'f', 'i', 'n', 'e'}; //s不是字符串
(b) 用字符串为字符数组初始化

char s[10] = {"I am fine"}; char s[10] = " I am fine";
s是字符串, ‘\0 ’系统自动添加

(c) 字符串数组初始化
对二维数组以字符串形式初始化。对于二维字符数 组,用两个下标表示数组中的一个字符。

char a[4][8]={"COBOL", "FORTRAN", "PASCAL", "C/C++"};

GuangXi University

23

C/C++
程序设计

4.3字符串

注意不要出现下面的错误:

? char s[10]={“This is a book”};//长度超过了 ? char s[10];
s = “I am fine”;//不能将字符串常量赋给地址 常量
? char s[10];
s = {‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’, ‘f’, ‘i’, ‘n’, ‘e’};//同样 不能将一系列字符赋给地址常量
? char s[3][4]; ? s[7]=‘c’;//不能将二维数组当成一维数组访问

GuangXi University

24

4.3字符串
C/C++
程序设计
(3)字符数组的输入/输出

? 逐个数组元素的输入/输出

char s1[10];

for (i = 0; i<10; i++) //一定要输入10个字符

cin>>s1[i];

//s1中是字符,不是字符串

//C:scanf(“%c”,&s1[i]) //

for (i=0;i<10;i++)

cout<<s1[i]

//通过循环逐个输出

//C:printf(“%c”, &s1[i])

注意:a.输入时各输入项之间不需加空格分隔

b.输入多出的字符不会被处理

c.逐个字符输出

GuangXi University

25

4.3字符串
C/C++
程序?设计字符串整体的输入/输出

char s1[10],s2[2][5];

输入:

输出:

? cin>>s1;

? cout<< s1;

? gets(s1);//C:scanf("%s", s1); ? puts(s1);//C:printf("%s", s1);

? for( int i=0; i<2;i++)

? for( i=0; i<2;i++)

gets(s2[i]);

puts(s2[i]);

//C:scanf("%s", s2[i]);

//C:printf("%s", s2[i]);

注s1意、:s2中是字符串, '\0'自动添加

?使用cin>>s1;语句,字符串中不能有空格。这与scanf一样。

?gets()和puts()是对字符串整体输入/输出 ,应加#include “stdio.h” 命令。并且允许字符串中的空格,gets()以回车符‘\r’结束。

gets(字符数组名或字符指针变量名);

GuangXi Universpityuts(字符数组名或字符指针变量名)。

26

4.3字符串
C/C++
程序设计
?字符串输入函数gets() 没有提供限制输入字符串长度的方法,容易引起缓 冲区溢出,给黑客攻击以可乘之机。

?对输入字符串长度有限制的函数调用 fgets(buf, sizeof (buf), stdin);

?对于scanf,当用户的输入多于定义时,str数组将越界。所以scanf被公 认为最易遭到黑客攻击的函数之一。

?getline(cin,str, [定界符]);从输入流读入一串字符,直到出现下列情况: (1)到达文件尾,这样,输入流的edfbit被设置,调用方法file()或eof()都 将返回true; (2)遇到分界字符,默认为‘\n’,这种情况下,将把分界字符从输入流中删 除,而且不存储她; (3)读取的字符到达最大的允许值,它将设置输入流的failbit,这意味着 fail()方法返回true; //Attention !!!

?实际上,cin类中也有getline、get成员函数,详细地说明将在I/O流那一 章给出。

GuangXi University

27

C/C++
程序设计
(4)字符串处理函数

4.3字符串

在标准C++中使用下面函数时,应加#include "string.h"命令。

a. strlen(str)

功能:求str所指向的字符串长度。不包括字符串结束标志'\0'。

说明:str可为字符串常量、字符数组名或字符指针。

b. strlwr(str)

功能:将字符串中的大写字母转换成小写字母。

说明:str为字符字符串常量、数组名或字符指针。

c. strupr(str)

功能:将字符串中的小写字母转换成大写字母。

说明:str为字符字符串常量、数组名或字符指针。

GuangXi University

28

4.3字符串
C/C++
程序设计
d. strcpy(str1,str2) 功能:将str2所指的字符串复制到str1中。 说明:str1和str2为字符数组名或字符指针,str2还可以是字符 串常量。str1要有足够大的空 间。

设:char str2[10]= {"aaa"},str1[10];

? strcpy(str1,str2); ? str1={"bb"}; ? str1=str2;

e. strcat(str1,str2) 功能:将str2字符串内容连接到str1字符串内容的后面 说明:str1要有足够大的空间。 例如:

char s1[20] = "abcd";
cout<<strcat(s1, "kkk")<<endl; //s1中的内容变为 abcdk

GuangXi University

29

C/C++
程序设计
f. strcmp(str1,str2)

4.3字符串

功能:比较字符串str1和str2的大小。

说明:从左至右逐个字符进行比较ASCII码值,直到出现不相 同字符或遇到'\0'为止。

str1 小于 str2 str1 等于 str2

返回 -1 返回 0 strcmp("ABCD","BD";

str1 大于 str2 返回 1 // 结果为:-1

例4.8字符串处理函数示例
#include "stdio.h"

puts("Invalid password.\n");

#include "string.h" void main( )

else break;

{ char s[80];

}

while(1) { gets(s);

puts("pass\n");

if(strcmp(s,"pass"))

}

GuangXi University

30

4.3字符串
C/C++
程序设计
4.3.2 CString 类(补充)
对字符串的存取及有关操作,在VC开发平台下还可通过 MFC中的CString 类。 (1) 定义CString 类对象 CString 类的定义在“afx.h”头文件中 形式: CString 对象名; CString 对象名= "字符串常量" ; CString 对象名("字符串常量"); CString 对象名(‘字符’,int n); //重复产生n个相同的字符 如:CString s1="C/C++程序设计";
CString s('d',5);cout<<s; //s获得字符串"ddddd"

//CString类中有多个构造函数(多态)

GuangXi University

31

C/C++
程序设计

4.3字符串

(2) 输入/输出

例4. 补1 示例

#include "iostream.h"

#include "afx.h"

void main()

{ char c[80];

由于VC++并不能直接使用cin对

CString st1;

CString对 象进行操作,应

cout<<"请输入字符串: ";

利用字符数组间接输入

cin>>c;

st1=c; cout<<"输出结果: ";

CString对象可直 接通过cout输出

cout<<st1<<endl;

}

GuangXi University

32

C/C++
程序设计
(3)基本运算

4.3字符串

假设定义: CString st1("ASDFG"),st2,st3("DD");

运算符 含义

实例

结果

=

赋值

st2= "C++ 程 序 设计";
st3=st1;

st2的值为"C++程序设计" st3的值为"ASDFG"

+

字符串连接

st2=st2+"教程" st2的值为"C++程序设计教程"

+=

字符串连接并赋



>、<、

==

关系运算

>=、<=

、[ !]=

取指定位置的字 符 , 将 CString

GuangXi Universit对y 象看成数组

st2+="教程"
st1=="ASDF"
st1<st3
st1[0] st1[3]

在st2相同初值的基础上效 果同上
false true
'A' //第一个字符位置为0 'F'
33

C/C++
程序设计
(4)成员函数

4.3字符串

形式:函数值类型 CString对象.成员函数名(参数列表)

a.取子串

形式:CString Mid(int nFirst,int nCount)

//取字符串中nFirst位置开始的nCount个字符

CString Left(int nCount)

//取字符串的左边nCount个字符

CString Right(int nCount)

//取字符串的右边nCount个字符

有定义:CString s("12345" );

则:s.Mid(2,2)的值为34

s.Left(3)的值为123

GuangXi University

34

4.3字符串
C/C++
程序设计
例4.补2 利用Left函数,输出如图所示的结果。
分析: ① 确定每行显示字符 的 起 始 位 , 通 过 setw(n) 显 示 一个空格的位数来实现,也可 通过产生一个有若干个空格的 字符串后left(n) 显示n个空 格来实现。
② 显 示 可 变 的 , 利 用 left(n) 。

如果不利用left函数,你如 何输出如图所示的结果?

CString st1(' ',30); // 产生30个空 CString st2("ABCDEFGHIJKLMNOPQRS"); for(int i=1;i<=10;i++) cout<<st1.Left(10-i)<<st2.Left(2*i-1)<<endl;

GuangXi University

35

C/C++
程序设计

4.3字符串

b.查看字符串信息

int Find(TCHAR ch); //返回指定字符在串中的位置

int Find(LPCTSTR lpszSub); //返回指定子字符串在串中的位置

int GetLength();

//返回字符串的字符数

有定义:CString s ("ABCDEF"); 则:s.Find('C')的值为2
s.Find("BCD")的值为1 s.GetLength()的值为6

GuangXi University

36

4.3字符串
C/C++
程序设计
例4.补3 程序输入5个单词,显示最长的单词及长度。

#include "stdio.h“ #include "iostream.h“ #include "afx.h"

void main()

{ CString st1,maxst; char s[80]; int maxlen(0),len,i;

cout<<"输入单词 :"<<endl;

for(i=1;i<=5;i++)

{ gets(s);

st1=s;

len=st1.GetLength();

if (len>maxlen)

{ maxlen=len; //找最长的单词长度

maxst=st1;

//找最长的单词

}

}

cout<<maxst<<maxlen<<endl;

}

GuangXi University

37

C/C++
c.字程序符设串计修改

4.3字符串

void SetAt(int nIndex,TCHAR ch) //用字符替换指定位置的字符

int Insert(int nIndex, TCHAR ch) //将字符插入到指定位置前 int Delete (int nIndex,int nCount=1)

//从指定位置开始删除一个或多个字符

int Replace(TCHAR chOld, TCHAR chNew)

//将新字符替换字符串中的老字符

int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)

//同上,区别替换的是子字符串

有定义:CString s ("ABCDEF"); 则:s.SetAt(1, 'b'); cout<<s; //输出AbCDEF
s.Insert(1, 'b'); cout<<s; // 输出AbBCDEF s.Replace('g','k');cout<<s; //输出ABCDEF s.Replace("BCD","bc"); cout<<s; //输出AbcEF
GuangXi University

思考:
如何删 除字符串 中任意子 字符串?38

4.3字符串
C/C++
程序设计
例4.补4 对已知输入的字符串,用"定冠词"替换"The" 。
#include "iostream.h" #include "afx.h" void main() { CString st1("The There Then The Thara ");
cout<<"替换前st1= "<<st1<<endl; st1.Replace("The ","定冠词"); cout<<"替换后st1= "<<st1<<endl; }

GuangXi University

39

C/C++
程序设计
d.转换字符串

4.3字符串

void MakeUpper() //将字符串中的所有字符转换成大写

void MakeLower() //将字符串中的所有字符转换成小写

void MakeReverse() //将字符串中各字符的顺序倒转

void Empty() //将字符串中的所有字符删除

有定义:CString s ("ABCabc");

则:s. MakeUpper(); cout<<s; 输出:ABCABC

s. MakeReverse(); cout<<s; 输出:cbaCBA

s. Empty();cout<<s;

输出: (空)

GuangXi University

40

C/C++
程序设计

4.3字符串

e.格式化输出

形式:viod Format(格式字符串,输出参数列表);

功能:构造一个输出的字符串,类似于C中的printf。

其中:

① “格式字符串”由输出的文字和数据格式说明符组成,文

字可以是直接键入的各种字符,还可以是转义符;数据格 式说明符形式: %[输出宽度]格式字符----常用格式

d/c/s/f/lf

② “输出参数列表” 表示要输出的数据,其个数与类型必须 与格式说明符依次对应。 有定义:CString s;

则:s.Format("a1=%d,a2=%5.2f,a3=%s",123,12.3,"abc");

cout<<s;

输出:a1=123,a2=12.30,a3=abc

GuangXi University

41

4.3字符串

C/C++
程序例设4计.补5 利用Format函数显示10o~180o之间每隔10o对应

的弧度、sin、cos、平方根和e指数的函数值。要求:

除第一项是角度占3位整数外,其余各项宽度为10、小

数占5位。
#include "iostream.h“ #include "math.h"

#include "afx.h"

void main()

{ CString s,sl('-',55); int i; float x;

cout<< " 数学函数表"<<endl;

cout<<sl<<endl; //显示55个'-'字符

cout<<"i x sin(x) cos(x)

sqr(i) exp(x) "<<endl;

for(i = 10;i<=180;i=i+10)

{ x = i * 3.14259 / 180;

s.Format("%3d%10.5lf%10.5lf%10.5lf%1

0.5lf%10.5lf\n",

i,x,sin(x),cos(x),sqrt(x),exp(x));

cout<<s;

}

Gu}angXi University

42

4.3字符串
C/C++
程序设计
例4.补6 使用CString 类对象数组存放若干个字符串,采用选
择法排序,实现对字符串数组的排序。

#include "iostream.h"

#include "afx.h"

void main() { CString

C/c++

s[4]={"Fortran","C/c++","Pascal","Visua l Basic"},t;

Fortran

int i,j,m; for(i=0;i<3;i++)

//选择法排序

Pascal

{ m=i;

for (j=i+1;j<4;j++)

Visual Basic

if (s[j]<s[m]) m=j;

t=s[i]; s[i]=s[m]; s[m]=t;

}

for (i=0;i<4;i++)

cout<<i<<" "<<s[i]<<endl;

}

GuangXi University

43

C/C++
程序设计

4.4指针与数组

指针可以指向基本数据类型变量(第二章),

也可以指向数组或数组元素。实际上数组名就

是起始地址。

4.4.1 指针和一维数组

4.4.2 指针和二维数组

4.4.3 指针和字符串

4.4.4 指针的补充说明

GuangXi University

44

C/C++
程序设计

4.4指针与数组

4.4.1 指针和一维数组

设有定义:

int a[6]={10,20,30,40,50,60},*p=a;

下面是引用数组元素的三种方式。

1.下标方式

假设有定义

形式: 数组名[下标] float a[10], *p = a;

2. 地址方式

则如下在值上的关系成立:

形式: *(地址常量) (1) p <=> a <=> &a[0]

3. 指针方式

(2) p+i <=> &a[i]

形式: *指针变量名 (3) *(p+i) <=> *(a+i) <=> a[i]

(4) 指针可以作数组名用

GuangXi University

即:p[i]<=>a[i] 45

C/C++
程序设计
例4.9 (1)四种方式输入数据 设有:int a[10];
p = a; for(i = 0; i<10; i++)
cin >>a[i]; 则等价于:
p = a;
for (i = 0; i<10; i++)
cin>>*p++;

4.4指针与数组

p = a; for (i = 0; i<10; i++,p++)
cin>>*p;

p = a; for (i = 0; i<10; i++)
cin>>*(p+i);//cin>>p[i]
GuangXi University

思考:第三种方法与其它二种区别

何在?

P指针变量的值不变

46

4.4指针与数组
C/C++
程序设计
例4.9 (2)分别用三种方式访问并显示数组中的所有元素。

#include “iostream.h”

void main()

{

int a[6]={10,20,30,40,50,60},*p=a,i;

cout<<“\n下标方式:”;

for(i=0;i<6;i++) cout<<a[i]<<“ ”;

//cout<<flush;

cout<<“\n地址方式:”;

for(i=0;i<6;i++) cout<<*(a+i)<<“ ”;

cout<<“\n指针方式:”;

for(i=0;i<6;i++) cout<<*(p+i)<<“ ”;

cout<<endl;

}GuangXi University

思考:按(1)的思路,还 可以写成什么形式?

47

C/C++
程序设计

4.4指针与数组

分析下列程序,思考:数组元素能否正确输出?

#include <iostream.h> void main( ) { int a[10], i, *p; p = a; for (i = 0; i<10; i++)
cin>>*p++;; for (i = 0; i<10; i++,p++)
cout<<*p; }



GuangXi University

48

4.4指针与数组
C/C++
程序设计
说明:(1)三种引用方式比较

引用方式 数组元素地址 数组元素值

特点

下标 地址

&a[i] a+i

a[i] *(a+i)

引用速度慢,要先计算地址a+i的值,指 向该元素后存取,比较直观。

指针

p+i

p++

*(p++i) *p

指针变量所指地址不变 速度快,不直 指针变量所指地址改变 观。

(2) p与a的区别:p是地址变量,而a是地址常量。 ? p++ 、p-- 、p=p+2
? a++、a=a+2

GuangXi University

49

C/C++
程序设计

4.4指针与数组

(3) *p++ 与 (*p)++区别: *p++的++运算符作用于指针变量; (*p)++的++运算符作用于指针变量所指对象。

设有定义:int a[6]={10,20,30,40,50,60},*p=a+2;

分别执行下面两段代码,思考每行代码的输出:

The fisrt:

cout<<*p++; //输出?

30

cout<<*p; //输出?

40

cout<<(*p)++; //输出? 30

The Second: cout<<*p;

//输出? 31

GuangXi University

50

4.4指针与数组
C/C++
程序设计
4.4.2 指针和二维数组(若干个一维数组组成)

定义二维数组:int a[n][m]; 则

a – 代表二维数组的首地址,第0行的地址

a+i

– 代表第i行的地址 *(a+i) 即 a[i]

元素a[i][j]的地址的几种等价的引用方式 &a[i][j]

– 代表第i行第0列的地址 *(a+i)+j 即 a[i]+j
– 代表第i行第j列的地址

a[i]+j *(a+i)+j &(*(a+i))[j] 元素a[i][j]的几种等价的引用方式

*(*(a+i)+j ) 即 a[i][j] – 代表第i行第j列的元素

a[i][j] *(a[i]+j) *(*(a+i)+j)

(*(a+i))[j]

GuangXi University

51

C/C++
程序设计
如设有定义: int a[2][3];

4.4指针与数组

? 数组名a可以解释为指向int类型的二级指针常量;a可以看 成是由两个元素a[0]、a[1]构成的一维数组。

? a[0]可以看成是由a[0][0]、a[0][1]、a[0][2] 3个整型变量组 成的一维数组,可将a[0]解释为指向int类型的一级指针常量; a[1]具有a[0]相同的性质。

?指针方式引用二维数组元素的两种方式:指针变量引用数组 元素、指针数组元素引用数组元素。

GuangXi University

52

4.4指针与数组
C/C++
程序设计
(1)指针变量引用数组元素
a.采用列指针(一级指针)
p+1
设有定义:int a[2][3],*p=a[0];

//或用p=*a初始化 通过p指针显示二维数组的各元素:

for(i=0;i<6;p++,i++) { cout<<*p<<" "; if(i%3==0)cout<<endl; }
GuangXi University

注意:在C++中二级指针地址 不能赋值给一级指针变量:
如:int a[2][3],*p=a;
在标准C中是允许的,但在
C++中就不允许。
53

C/C++
程序设计

4.4指针与数组

b.采用行指针(二级指针)----数组指针

设有定义:int a[2][3],(*p)[3]=a;

//或p=a初始化;

通过p指针显示二维数组的各元素: p+1

for(int i=0;i<2;i++) {for (int j=0;j<3;j++)
cout<<(*p)[j]<<" "; p++; cout<<endl; }

for(int i=0;i<2;i++) {for (int j=0;j<3;j++)
cout<<*((*p)+j)<<" "; p++; cout<<endl; }

p等效于二维数组名a,但没有指出其边界,即第一维的 元素数量,但是它的较低维数的元素数量必须要指定。

GuangXi University

54

C/C++
程序设计

4.4指针与数组

(2)指针数组引用数组元素

指针数组的形式: 数据类型 *标识符[整型常量表达式]; 即:数组中每个元素是指针。 设有定义:

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

要引用a[i][j]元素,可用指针数组表示如下: *(p[i]+j) 或 *(*(p+i)+j)

注意:

指针数组名p与二维数组名a都是二级指针的概念,区别在于: a[i]是地址常量,p[i]是地址变量。

GuangXi University

55

4.4指针与数组

C/C++
程序设计
例4.10 数组指针与指针数组示例

//第二种方式输出

#include "iostream.h"

for(i=0;i<3;i++)

void main()

{for (j=0;j<4;j++)

{int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; cout<<*((*p0)+j)<<" ";

int i,j;

p0++;

//列指针示例

cout<<endl;

int *p=a[0];

}

for(i=0;i<12;p++,i++)

cout<<endl;

{ cout<<*p<<" ";

//第三种方式输出

if((i+1)%4==0) cout<<endl;

p0=a;//重新指向a

}

for(i=0;i<3;i++)

cout<<endl;

{for (j=0;j<4;j++)

//数组指针(二级指针--行指针)示例

cout<<(*p0)[j]<<" ";

int (*p0)[4]=a; //[]的优先级高于*, p0是一个 p0++;

指针变量

cout<<endl;

//指针数组示例

//对一维数组

int c[4]={1,2,3,4};

int *p1[4]={&c[0],&c[1],&c[2],&c[3]}; //p1是四个指针,这四个指针组成一个 数组

for(int k=0;k<4;k++)

cout<<*p1[k]<<endl;

cout<<endl; //对二维数组

int

b[2][3]={1,2,3,4,5,6},*p2[2]={b[0],b[1]}

,kk,jj;

for(kk=0;kk<2;kk++)

{

for(jj=0;jj<3;jj++)

//第一种方式输出 for(i=0;i<12;i++) { cout<<(*p0)[i]<<" ";
if((i+1)%4==0) cout<<endl; } cout<<endl;

}
cout<<endl; //第四种方式输出
p0=a; //重新指向a for(i=0;i<3;i++)
{for (j=0;j<4;j++)

cout<<*(p2[kk]+jj)<<' '; cout<<endl; } cout<<endl; }

cout<<p0[i][j]<<" ";

cout<<endl;

}

GuangXi University

cout<<endl;

56

C/C++
程序设计

4.4指针与数组

4.4.3 指针和字符串

(1)可通过字符指针来访问字符数组,二者的区别:

字符数组

字符指针

定义

char s[6];

char *p;

初始化 char s[]="china";

char *p="china";

char *p=s;

赋值

s[0]='c';s[1]='h';
//逐个赋值
cin>>s; gets(s);

p="china"; //指向字符串常量的首地址
p=new char[6]; 或 p=s;
//应使字符指针有确定指向后才能从键盘进 行输入操作
cin>>p; 或 gets(p);

运算 字符数组名s不能进行 自增或自减运算
GuangXi University

p是指针变量,可以进行自增或自减 运算
57

4.4指针与数组
C/C++
程序设计
例4.11输入一串字符存储在字符数组中,用指针方式逐一显示字符,
并求其长度。

#include "iostream.h"

#include "stdio.h"

void main()

{ char s[80],*p;

gets(s);

p=s;

//p指向数组的第一个元素

cout<<"输出每个字符:";

while(*p!='\0')

cout<<*p++<< " "; //指针下移,直到p指向字符串结束符 cout<<"\n 字符串长度 : "<<p-s<<endl;

} GuangXi University

58

4.4指针与数组
C/C++
程序设计
(2)字符指针数组,常用于处理若干字符串。
设有定义:
char *book[]={"Fortran", "C/c++", "Pascal", "Visual Basic"}; 即:数组book中每个元素是指向字符串的指针。

? 按字符串的实际长度存储,以'\0'表示每个字符串的结束。

? 采用交换指针值的方法改变指针的指向。

GuangXi University

59

C/C++
程序设计

4.4指针与数组

例4.12 对4个字符串,按字典顺序将它们排序输出。

#include "iostream.h"

#include "string.h"

void main()

{ char *book[]={"Fortran","C/c++","Pascal","Basic"},*p;

int i,j,k;

for(i=0;i<3;i++) { k=i; for(j=i+1;j<4;j++)

注意元素的比 较

if(strcmp(book[k],book[j])>0) k=j;

if(i!=k) { p=book[i];book[i]=book[k]; book[k]=p;}

}

for(i=0;i<4;i++)

cout<<book[i]<<endl;

} GuangXi University

60

4.4指针与数组
C/C++
程序设计
4.4.4指针的补充说明

指针学习不好关键是概念不清造成的,说的

简单点就是书没有认真看,指针的学习犹如人在 学习饶口令不多看多学多练是不行的。

学习原则

– 一定要学会 – 其实通常的应用很简单,与使用变量几乎无异 – 仔细琢磨 使用原则

– 永远要清楚每个指针指向了哪里

– 永远要清楚指针指向的位置是什么

我们还是给几个例子来说明。

GuangXi University

61

4.4指针与数组
C/C++
程序设计
例:用变量a给出下面的定义

?一个整型数 a) int a;

?一个指向整型数的指针 b) int *a;

?一个指向指针的指针,它指向的指针是指向一个

整型数

c) int **a;

?一个有10个整型数的数组 d) int a[10];

?一个有10个指针的数组,该指针是指向一个整型 数的 e) int *a[10];

?一个指向有10个整型数数组的指针 f) int (*a)[10];

GuangXi University

62

4.4指针与数组
C/C++
例:程序分设析计下面程序的功能

#include <stdio.h>

此题并没有改变变量

main()

a,b的值,利用指针

{ int a,b; int *point_1,*point_2,*temp_point; scanf("%d,%d",&a,&b);
point_1=&a;
point_2=&b; if (a<b)

变量分别存储a和b 的地址,然后若a<b, 把那两个指针变量的 值对换一下,再利用 *point_1和*point_2 的方式把调换后的值

{ temp_point=point_1; point_1=point_2;
point_2=temp_point;

显示出来。利用指针 进行地址交换达到大 小排序的目的.

} printf("%d,%d",*point_1,*point_2);

}GuangXi University

63

C/C++
程序设计

4.5动态数组

在<stdlib.h> 和<alloc.h>中均定义了下面 的函数
void* malloc(unsigned int size);
– 向系统申请大小为size的内存块,把首地址返回。 如果申请不成功,返回NULL
void *calloc(unsigned int num, unsigned int size);
– 向系统申请num个size大小的内存块,把首地址返 回。如果申请不成功,返回NULL
void free(void* p);
– 释放由malloc()和calloc()申请的内存块。p是 指向此块的指针

GuangXi University

64

C/C++
程序设计

4.5动态数组

一维动态数组 #include <stdlib.h> main() {
int *p = NULL, n, i, sum; printf("Please enter array size:"); scanf("%d", &n); p = (int *) malloc(n * sizeof (int)); if (p == NULL) { printf("No enough memory!\n"); exit(0); } printf("Please enter the score:"); for (i=0; i<n; i++) { scanf("%d", p + i); } sum = 0; for (i=0; i<n; i++) { sum = sum + *(p + i); } printf("aver = %d\n", sum/n); free(p); }

GuangXi University

65

C/C++
程序设计

4.5动态数组

二维动态数组 #include <stdlib.h> main() {
int *pScore = NULL, i, j, m, n, maxScore, row, col; printf("Please enter array size m,n:"); scanf("%d,%d", &m, &n); pScore = (int *) calloc(m*n, sizeof (int)); if (p == NULL) { printf("No enough memory!\n"); exit(0); } printf("Please enter the score:"); for (i=0; i<m; i++) {
for (j = 0; j<n; j++) {
scanf("%d", &pScore [i*n+j]); } } maxScore = FindMax(pScore, 3, 4, &row, &col); printf("maxScore = %d, class = %d, number = %d\n",
maxScore, row+1, col+1); free(pScore ); }

GuangXi University

66

C/C++
程序设计
1. 插入数据

4.6应用举例

基本思想:

1)首先要查找待插入数据在数组中的位置k;

2)然后从最后一个元素开始往前直到下标为k的元素依次往后移动 一个位置;

3) 第k个元素的位置空出,将欲插入的数据插入。

④③②①

1 4 7 10 13 16 19 22 25

x 14 k

例4.13 在有序数组a中插入数值x

for(k=0;k<9;k++) if (x<a[k]) break; // 找到插入的位置下标为k

for(i=8;i>=k;i--) a[i + 1] = a[i]; //从最后元素开始往后移,腾出位置

Guaan[gkXi]U=nivxer;sity

67

4.5应用举例
C/C++
程序设计
2. 删除数据 删除操作首先也是要找到欲删除的元素的位置k;然后从k+1到
n个位置开始向前移动;最后将数组元素减1。

42

68

35

1

70

25

79 k

① 59

② 63

③ 65

例4.14 从数组中删除某数。

for(i=0;i<10;i++) if(key==a[i])break;
for(j=i;j<10;j++) a[j]=a[j+1];

GuangXi University

68

C/C++
程序设计
3. 二分法查找

4.5应用举例

分析:二分法查找只适合于在已排好序的数组中进行。

设a[low]和a[high]是有序数组中最小和最大元素,待查找的数为x。

算法描述如下:

① 开始假设待查区间的下界low为0,上界high为N-1。

② 求待查区间中间元素的下标mid = (low+high)/2,x和a[mid]比较。

③ 若x==a[mid],则查找完毕,结束程序;若x>a[mid],则继续查找的 范围应为a[mid]后面的元素,修改查找区间的下界low = mid+1;若 x<a[mid],则继续查找的范围应为a[mid]前面的元素,修改查找区间的 上界high = mid-1;

④ 重复第2、3步,直到找到x;

或low>high无查找区域,找不到。

GuangXi University

69

C/C++
程序设计

4.5应用举例

GuangXi University

70

C/C++
程序设计

4.5应用举例

其中,第3步可用如下程序段实现:

if (x==a[mid]) break;
else if (x>a[mid]) low=mid+1;
else high=mid-1;

请编出完整的程序。

GuangXi University

71

C/C++
程序设计
4. 分类统计

4.5应用举例

例4.15 统计一串字符中各字母出现的次数(大小写字母不区分),并 对出现的字母显示其出现的个数和总字母数。

分析:
① 声明一个具有26个元素的数组,每个元素的下标表示对应的字 母,元素的值表示对应字母出现的次数。
② 从输入的字符串中逐一取出字符,转换成大写字符(使得大小写 不区分),进行判断。

GuangXi University

72

C/C++
程序设计

4.5应用举例

#include "iostream.h“ #include "stdio.h“ #include "afx.h" void main() { CString st1; char s[256],c; int a[26]={0},i,j,le,sumc(0);
gets(s); st1=s; le =st1.GetLength(); // 求字符串的长度 st1.MakeUpper(); //转换成大写 for(i=0;i<le;i++)
{ c =st1[i]; if (c >= 'A' && c <= 'Z') { j = c-'A'; a[j] ++; }
} for(j=0;j<=25;j++) //'输出字母及其出现的次数
if (a[j] ) {sumc=sumc+a[j];st1.Format("%c=%d ",j+65,a[j]); cout<<st1;}
cout<<"共有"<<sumc<<"个字母"<<endl; }

GuangXi University

73

C/C++
程序设计

4.5应用举例

5. 数制转换
例4.16 将一个十进制整数m转换成二至十六r 进制的字符串
基本思想:
将m不断除r取余数(若余数超过9,还要 进行相应的变换,例如10变换成A,11变换 成B等),直到商为零,以反序得到结果, 即最后得到的余数在最高位。

GuangXi University

74

C/C++
程序设计

4.5应用举例

#include "iostream.h"

#include "afx.h"

void main()

{ CString s;

char c;

int m,r,mr0;

do

{ cin>>m>>r; }

while (m<0 || r<2 ||r>16 );

while (m !=0) { mr0 = m % r;

//取余数

if (mr0 > 9) c=mr0-10+'A'; else c=mr0+'0';

s=c +s; m = m / r;

} cout<<"结果为 "<<s<<endl;

}

GuangXi University

75

C/C++
程序设计

小结

回忆一下,本章你学习了些什么? 回忆一下,本章你学习了些什么? 回忆一下,本章你学习了些什么?

GuangXi University

76


相关文档

《指针与二维数组》PPT课件
指针与二维数组ppt课件
最新文档-四章数组与指针ppt课件-PPT精品文档
四章数组与指针ppt课件
第4讲数组、指针与字符串-PPT课件
第6章数组指针与字符串-PPT精品文档
第04章C 数组与指针-PPT文档资料
C语言程序设计PPT课件第11章 指针和数组-PPT精选文档
二级C语言PPT教学课件,08_整型指针与数组
学霸百科
80093383文学网 800933831php网站 800933832jsp网站 800933833小说站 800933834算命网 800933835占卜网 800933836星座网
电脑版 |