3.2 一维数组

Download Report

Transcript 3.2 一维数组

Slide 1

第3章 数 组

第3章 数 组


教学内容:

数组的基本概念;一维数组的声明,初始化和引用;多维数
组的声明,初始化和引用;数组作为函数的参数;数组与字符串;
构造数据类型。


教学要求:

掌握数组的基本概念,学会使用一维数组、多维数组编程,
掌握数组作为函数参数的使用方法;
熟练掌握字符串的基本操作;
了解构造数据类型的使用方法。


Slide 2

第3章 数 组

第3章 数 组
3.1 数组的基本概念

3.2 一维数组
3.3 多维数组
3.4 数组作为函数的参数
3.5 数组与字符串
3.6 数组应用举例

3.7 构造数据类型


Slide 3

第3章 数 组

3.1 数组的基本概念
数组是一种构造数据类型,是具有统一名称和相
同类型的一组数据元素的集合,它占用连续内存单元
进行存储。要引用数组中的特定位置或元素,就要指

定数组中的特定位置或元素的位置号 (position number)。


Slide 4

第3章 数 组

图3-1 整型数组c的数组元素存储分配示意


Slide 5

第3章 数 组

3.2 一 维 数 组
3.2.1 一维数组的声明
数组在使用前必须先声明。声明一个一维数组的形式如下:
<类型标识符> <数组名>[数组长度]其中:

① 数组名必须遵循C++语言对标识符的要求,其命名规则与
其它变量名的相同。
② 数组长度是个常量表达式,它规定了数组的大小,即所声

明的数组由多少个数据类型相同的存储空间组成。


Slide 6

第3章 数 组

数组的声明为以后使用数组分配了存储空间,数组中
每个元素在内存中是依次排列的。例如,int Score[50];定
义了名称为Score的一维数组,该数组有50个元素,是int类
型的。
在声明数组时,要注意数组的长度只能由常量表达式
来决定,不能是变量。即,数组的长度必须是确定的。例
如:
int nMonth;
float fSales[nMonth *12];
是错误的。这个声明在编译时编译器会给出错误信息。


Slide 7

第3章 数 组

3.2 一 维 数 组
3.2.2 一维数组中的元素访问
数组中的每个元素可以当成普通的变量使用。访问

一维数组元素的形式如下:
<数组名>[下标]
下标就是元素索引值,它代表了要被访问的数组元

素在内存中的相对位置。下标值的允许范围从0开始到数
组长度-1。下标等于0代表要访问的元素在数组的第1个位
置上,下标等于1代表要访问的元素在数组的第2个位置
上,依次类推。


Slide 8

第3章 数 组

例如,声明一个长度为20的整型数组,并将数组中的
各个元素按顺序赋予从50到70以1递增的数,即赋予数组
的第0个元素的值为50,赋予数组的第1个元素的值为51,
依此类推。写出相应的程序段。
程序段代码如下:
int nData[20];
for(int nIndex=0;nIndex<20;nIndex++)
nData[nIndex]=nIndex+50;


Slide 9

第3章 数 组

【例3-1】 生成一个长度为10的连续偶数序列,该
偶数序列从2开始。要求将此序列保存在数组中,并输
出此数组的每个元素的值。
分析:显然,先要声明一个长度为10的数组。模

仿上面的做法,可以用一个循环来解决对所有数组元
素的访问,关键在于生成数列。偶数列是个很简单的
数列,如果从0开始, 则规律为:第i个数等于i*2(i=0,

1,2,…);如果从2开始,则规律为:第i个数等于
i*2+2(i=0,1,2,…)。


Slide 10

第3章 数 组

程序代码如下:
#include
void main( )
{
int nEven[10];

//定义用于存放10个偶数的数组

int nIndex;
for(nIndex=0;nIndex<10;nIndex++)
nEven[nIndex]=nIndex *2+2;

for(nIndex=0;nIndex<10;nIndex++)
{


Slide 11

第3章 数 组

cout<}
cout<}
程序运行结果为

2 4

6

8

10

12

14

16

18

20


Slide 12

第3章 数 组

3.2.3 一维数组的初始化
变量可以在声明时赋初值,数组也可以在声明时给所
有或部分数组元素赋初始值。要给一维数组元素赋初始值,
有如下两种形式。


形式1:
<类型标识符> <数组名>[数组长度]={第0个元素值,第

1个元素值, …, 第n-1个元素值}


形式2:

<类型标识符> <数组名>[ ]={第0个元素值,第1个元素
值,…,第n-1个元素值}


Slide 13

第3章 数 组

【例3-2】 一个班级有20名学生,所有学生的英语
考试成绩保存在一个一维数组中。编写程序,求出该班
学生的英语考试平均成绩,并统计考试成绩在90分以上
(包括90分)的学生人数和不及格的学生人数。
分析:为了统计平均成绩,需要有个变量保存所
有学生的成绩总和。求总和的方法就是在对每个数组元
素访问时,将其值累加到这个变量中,然后由此变量除
以学生人数即得平均成绩。要统计考试成绩90分以上的
学生人数和不及格的学生人数,需要分别设置两个变量。
在对每个数组元素进行访问时,如果元素值大于等于90,
就将保存考试成绩在90分以上的学生人数的变量值加1;
如果元素值小于60,就将保存考试成绩不及格的学生人
数的变量值加1。


Slide 14

第3章 数 组

#include
void main( )
{
int
nScore[20]={90,88,45,92,76,59,89,93,60,51,91,65,82,74,92,
35,66,78,62,91};
//用数组初始化的方法将成绩存于数组nScore中
int nUnPassedCount=0;

//定义记录不及格人数的变量

int nHighScoreCount=0; //定义记录90分以上人数的变量
int nSum=0;

//定义求和的变量


Slide 15

第3章 数 组

for(int ni=0;ni<20;ni++)
{
nSum+=nScore[ni];
if(nScore[ni]<60)
nUnPassedCount++;

if(nScore[ni]>=90)
nHighScoreCount++;
}

cout<<"平均分数为:"<<(float)nSum/20<

Slide 16

第3章 数 组

cout<<"90分以上人数为:"<cout<<" 不及格人数为:"<}
程序运行结果为
平均分数:73.95
90分以上人数为:6
不及格人数为:4


Slide 17

第3章 数 组

3.3 多维数组
3.3.1 多维数组的声明
声明一个多维数组的形式如下:

<类型标识符> <数组名>[长度1][长度2]…[长度n]
同一维数组相同,多维数组的数组名必须遵循C++语
言标识符的命名规则,常量表达式中不能有任何变量出现。
为了更直观地介绍多维数组,下面以二维数组为例。


Slide 18

第3章 数 组

声明一个二维数组的形式如下:
<类型标识符> <数组名>[第1维长度][第2维长度]

例如,语句float fMatrix[3][4]将声明一个数组名为
fMatix且第1维长度为3、第2维长度为4的二维数组。在
二维数组中,第1维常常称为行,第2维常常称为列。

这样,一个二维数组就可同一个二维表格对应起来,
如表3-1所示。


Slide 19

第3章 数 组

表3-1 二维数组与表格



0

1

2

3

0

fMatrix[0][0]

fMatrix[0][1]

fMatrix[0][2]

fMatrix[0][3]

1

fMatrix[1][0]

fMatrix[1][1]

fMatrix[1][2]

fMatrix[1][3]

2

fMatrix[2][0]

fMatrix[2][1]

fMatrix[2][2]

fMatrix[2][3]




Slide 20

第3章 数 组

可以这样理解二维数组:如果只给出二维数组的第1

维下标,以一维数组来看二维数组,则这样的数组中每
个元素所代表的是另一个一维数组。
例如,fMatrix[0]代表由4个f1oat类型的元素组成的另
一个一维数组(数组名为fMatrix[0],元素为fMatrix[0][0]、
fMatrix[0][1]、fMatrix[0][2]、fMatrix[0][3])。不难算出,
fMatrix中共有3*4=12个fIoat型元素。


Slide 21

第3章 数 组

3.3.2 访问多维数组中的元素
要访问多维数组中的元素,同样需要指定要访问的元素的下
标。多维数组的元素有多个下标,其书写形式如下:
<数组名>[第1维下标][第2维下标] … [第n维下标]
下标的值也是从0开始,不能超过该维的长度减1。下标的值
可以是任意表达式的值,只要其值在该下标的有效范围内即可。


Slide 22

第3章 数 组

3.3.3 二维数组的初始化
同一维数组一样,二维数组也可以在声明时赋初始值,
其形式如下。


形式1:
<类型标识符> <数组名>[第1维长度][第2维长度]={第0

个第2维数据组},{第1个第2维数据组},…,{第n-1个第2
维数据组}}
其中,n等于第1维长度。


Slide 23

第3章 数 组



形式2:
<类型标识符> <数组名>[第1维长度][第2维长度]={第0个元

素值,第1个元素值,…,第m个元素值}
其中,m小于或等于第1维长度乘以第2维长度。
在两种形式中,如果花括号中给出的元素个数少于实际的元

素个数,则剩余的元素就不会被赋予初始值;如果花括号中给出
的元素个数大于实际的元素个数,则编译器会给出错误信息。


Slide 24

第3章 数 组

【例3-3】

生成如下格式的方阵,将其存入二维数

组中,并输出这个二维数组所有元素的值。
1

2

3

4

5

10 9

8

7

6

11 12 13 14 15

20 19 18 17 16
21 22 23 24 25


Slide 25

第3章 数 组

分析:注意到这个方阵的规律在于,偶数行中的
元素按升序排列,奇数行中的元素按降序排列,只要
逐行处理方阵中的元素,即可得到这种方阵。为了访
问二维数组中的所有元素,应使用二重嵌套循环。外
层循环的循环控制变量作为当前行,内层循环的循环
控制变量作为当前列。在显示这个二维数组时,为了

得到理想的显示效果,要对不同的元素指定不同的显
示位置。


Slide 26

第3章 数 组

程序代码如下:
#include

void main( )
{
int nRow;

//控制行的变量

int nCol;

//控制列的变量

int nMatrix[5][5];

//声明二维数组

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


Slide 27

第3章 数 组
{
for(nCol=0;nCol<5;nCol++)
{

if(nRow%2==0)
nMatrix[nRow][nCol]=nRow*5+nCol+1;
else
nMatrix[nRow][4-nCol]=nRow*5+nCol+1;
}
}
for(nRow=0;nRow<5;nRow++)
{


Slide 28

第3章 数 组
for(nCol=0;nCol<5;nCol++)
{
cout<if(nMatrix[nRow][nCol]<10)

//控制输出1位数与2位

数时的不同间隔
cout<<" ";
else
cout<<" ";
}
cout<}
}

//每输出一行后换行


Slide 29

第3章 数 组

3.4 数组作为函数的参数
在C++语言中,将整个数组作为参数传递给函数要涉

及到指针的概念。有关内容将在本书的第6章进一步讨论,
这里只结合数组参数的传递过程做简单介绍。
要将数组作为参数传递给函数,可由不带方括号的数

组名进行。


Slide 30

第3章 数 组

例如,如果数组声明如下:
int nMatrix[20];
则将数组传递给函数,可用下列函数调用语句:
myArray(nMatrix,20);
要传递数组,大体上有以下两种形式。



形式1:
<类型标识符> <函数名>(类型标识符 数组名[ ],int

长度)



形式2:
<类型标识符> <函数名>(类型标识符 数组名[长度])


Slide 31

第3章 数 组

数组名的值实际上就是保存数组中第0个元素的内

存地址的变量,这样的变量称为指针型变量。当进行
数组传递时,实际参数将此地址值传递给形式参数,
使形式参数同实际参数指向同一内存地址。这样在函
数中如果改变数组中某个元素的值,在函数外数组中
该元素的值也发生改变。


Slide 32

第3章 数 组


Slide 33

第3章 数 组

例3-4】 某次歌唱比赛有5名选手参加,有6名评委
分别为选手打分,得分如表3-2。
选手号

1

2

3

4

5

1

2

3

4

5

6

9.31

9.20

9.00

9.40

9.35

9.20

9.71

9.52

9.50

9.66

9.49

9.57

8.89

8.80

9.10

9.25

8.90

9.00

9.38

9.50

9.40

9.20

9.90

8.90

9.30

8.84

9.40

9.45

9.10

8.89


Slide 34

第3章 数 组

规定的积分规则是:每位选手去掉一个最高分,再
去掉一个最低分,然后取剩下的得分的平均分。编写程
序计算各选手的成绩,并在窗口输出选手号和成绩。
分析:由于二维数组同二维表格有对应关系,可以
用一个二维数组保存所有评委给所有选手评出的成绩。
这样,数组下标的第1维(行)代表的就是选手号——i,

第2维(列)代表的是评委号——j。


Slide 35

第3章 数 组

在找数组各行元素最大值、最小值的同时还应对
数组元素求和,这样,访问完一位选手的所有得分后,
就可以得到该选手得分的总和、最高分和最低分。将
得分总和减去最高分、最低分,然后再除以4,就得到
选手的最后得分。
程序代码如下:
#include
double Context(double pArry[],int nNum)//评分函数
{


Slide 36

第3章 数 组

int nInum;
double fMark, fMax, fMin;//记录成绩、最高分、最低分的变量
fMark=fMax=fMin=pArry[0];
for(nInum=0;nInum{

if(pArry[nInum]>fMax)
fMax=pArry[nInum];
if(pArry[nInum]
fMin=pArry[nInum];


Slide 37

第3章 数 组

fMark+=pArry[nInum];
//fMark先记录着所有评委的总分

}
return (fMark-fMax-fMin)/4;
//计算出平均分并返回调用函数

}
void main( )
{
double pfSoreData[5][6]
{


Slide 38

第3章 数 组

{
{9.31,9.20,9.00,9.40,9.35,9.20},

{9.71,9.52,9.50,9.66,9.49,9.57},
{8.89,8.80,9.10,9.25,8.90,9.00},
{9.38,9.50,9.40,9.20,9.90,8.90},

{9.30,8.84,9.40,9.45,9.10,8.89}
};
int nRow;

cout.precision(3);

//设置小数点后的位数

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


Slide 39

第3章 数 组

{
cout<cout<
}
}
程序运行结果为
1号选手成绩:9.29
2号选手成绩:9.6
3号选手成绩:8.95
4号选手成绩:9.41
5号选手成绩:9.28


Slide 40

第3章 数 组

注意,本例中调用函数形式为
Context(pfSoreData[nRow],5),将二维数组的第1维数
组名作为实际参数传递给了形式参数。由此,可进一
步理解二维数组是若干个一维数组所组成的概念。


Slide 41

第3章 数 组

3.5 数组与字符串
在C++语言中没有字符串变量类型。为了表示字符串,
要用到字符数组,对字符串的处理是通过字符数组的每
一个元素保存字符串内的每一个字符来进行处理。而在
Visual C++中,是由其MFC类库中提供的功能完善的字符
串类CString来完成字符串的各种功能。


Slide 42

第3章 数 组

3.5.1 字符数组
字符型数组就是数组元素的类型是字符型的数组,简称为
字 符 数 组 。 例 如 , char CBuffer[256]; 、 unsigned char
pDBufrer[5][80]; 都是字符型数组。字符型数组的定义和声明同
普通数组没有什么区别,主要的不同之处在于字符数组元素的
初始化与使用方法。
字符型数组也可以用通常数组初始化的形式对其元素进行

初始化,只不过由于字符型数组中的元素是字符类型,一般用
字符型常量给字符型数组赋初值,例如:


Slide 43

第3章 数 组

char myChars[ ]={'T','h','i','s',' ','a', ' ' ,'c',
'o','m','p','u','t','e','r'};
除此以外,字符型数组常用两种特殊的初始化方法,
形式如下:


形式1:
char <数组名>[ ]="字符串“



形式2:
char <数组名>[ ]={"字符串"}

这两种形式产生的效果是相同的,它们会产生一个以
字符串常量中的每个字符为数组元素且在末尾加个“\0”
的特殊数组。例如:


Slide 44

第3章 数 组

char pMyStrinq[ ]="This is a computer";
执行后,pMyString数组中的元素依次是:

'T','h','i','s',' ','a','','c','o','m','p','u','t',
'e','r ','\0'
它等同于

char pMyString[ ]={'T','h','i','s',' ','a',' ','c',
'o','m','p','u','t','e','r ','\0'};


char pMyStrinq[ ]={"This is a computer"};


Slide 45

第3章 数 组

说明:
① 转义字符“\0”表示的是字符串常量中字符串的
结束标志,在末尾保存了0的字符型数组,也可以当成字
符串来使用。在程序中,凡是可以使用字符串常量的地
方,可以使用字符型数组来代替。
② 字符型数组也是数组,只不过赋初值的方法有点
特殊,但不能用赋值的方法进行赋初值。例如:
char pMyStrinq[ ];
pMyStrinq[ ]="This is a computer";
是错误的。


Slide 46

第3章 数 组

③ 变量可以重复赋值,即变量表示的值在程序运行
的过程中可以通过赋值语句改变,但是字符型数组只能
改变其元素的值,不能有“数组名=”字符串“;”这样的
赋值语句出现。
④ 数组的长度在声明时就已经确定(字符串中字符
个数+1),在使用的过程中不能更改。虽然在程序的运
行过程中可以通过改变数组元素的值来改变一个字符型
数组所存储的字符串内容,但如果要增加所存的字符串
的长度,用静态数组是办不到的。


Slide 47

第3章 数 组

3.5.2 字符串的基本运算

C++语言中没有字符串型变量,要实现字符串的运算,例如,

连接两个字符串,求字符串长度等,需要另外编写程序对字符
型数组进行操作。在C++语言的库函数中提供了各种字符串运
算的函数,可以直接调用。

 1.求字符串的长度
C++语言的标准字符串以'\0'结尾,所以求一个字符串的
长度,要从字符串的第一个字符算起,直到碰到'\0'为止。


Slide 48

第3章 数 组

假设字符串保存在数组pString中,求字符串长度的程序段

如下:
char pString[ ]="字符串";
int nSize=0;

while(pString[nSize]!= '\0')
nSize++;
执行完毕后,整型变量nSize中保存的值就是字符串pString

的长度。


Slide 49

第3章 数 组



2.字符串的复制
字符串的复制就是将一个字符型数组(源字符串)的

内容照原样复制到另一个字符型数组中。方法是:把源字
符型数组中的字符依次赋给目的字符型数组,直到碰到'\0'
为止。
假设源字符串保存在数组pSource中,目的字符型数
组为pDestination,则字符串复制的程序段如下:
char pSource[ ]="字符串";
char pDestination[N]; //N≥源字符串长度+1
int nIndex=0;


Slide 50

第3章 数 组

while(pSource[nIndex]!= '\0')
{
pDestination[nIdex]=pSource[nIdex];
nIndex++;
}

pDestination[nIdex]= '\0'; //标识字符串结束
最后的while循环语句还可简化写为
while(pDestination[nIdex]=pSource[nIndex++]);


Slide 51

第3章 数 组



3. 字符串的连接
字符串的连接就是将一个字符串连接到另一个字符

串的末尾。在进行字符串的连接时,先要找到要被连接
的字符串的尾部,然后从尾部的位置开始将另一个字符
串复制过来。
必须注意的是,存储原字符串的数组要有足够的空
间来容纳连接进来的另一个字符串,否则在运行时可能
产生保护模式错误。
假设原字符串保存在字符数组pDest中,要连接进来
的字符串存在字符数组pTocat中,则进行字符串连接的程
序段如下:


Slide 52

第3章 数 组

char pTocat[ ]="要连接进来的字符串";

char pDest[N]="现字符串"; //N≥现字符串长度+要连接进来的
字符串长度+1
int nSize=0;

int nIndex=0;
while (pDest[nSize]!=‘\0’) //找到要被连接的字符串的尾部
nSize++;


Slide 53

第3章 数 组

do
{
pDest[nSize++]=pTocat[nIdex];
nIdex++;
} while(pTocat[nIdex]!= '\0');
pDest[nSize]= '\0';


Slide 54

第3章 数 组

3.6 数组应用举例
3.6.1 排序
数组元素排序是与数组有关的最重要的算法。所谓
数组元素排序,是指将数组中的所有元素的位置重新排
列,使得数组元素的值按照递增或递减有序排列。例如,
已知一个一维数组中的元素按顺序是1、7、3、22、9、5,
以递增排序后,这个数组中元素的排列就变成了1、3、5、

7、9、22。排序有很多方法,本节介绍常用的选择排序
法和冒泡排序法。


Slide 55

第3章 数 组

【例3-5】 选择排序法例题。
选择排序法是很朴素的排序方法,它的思想很简
单:先找到数组中最大的元素,将这个元素放到数组
的最前端;然后在剩下的数组元素中再找出最大的元
素,把它放在剩下的这些元素的最前端。如此下来,
就能使数组中的元素以递减顺序排列了。选择排序法
的函数代码如下:


Slide 56

第3章 数 组

#include
void main( )

{
int a[6]={1,7,3,22,9,5};
int i,j,t,p;

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


Slide 57

第3章 数 组

for(j=i+1;j<6;j++)
if(a[p]>a[j]) p=j; //找本次最小元素的下标
if(i!=p)
{t=a[i];
a[i]=a[p];
a[p]=t;}
}
cout<<"排序后的数组为:\n";
for(i=0;i<6;i++)
cout<<" "<}


Slide 58

第3章 数 组

【例3-6】 冒泡排序法例题。
冒泡排序法是交换排序法的一种,其基本思路是:
两两比较待排序的序列中的相邻元素,如果不满足顺
序要求,就交换这两个元素。这样,第1轮比较完毕后,
数组中的最大(或最小)元素就像气泡一样“冒”到数组
的最尾部。可以认为由这个元素组成的只有一个元素
的子序列是已经排好序的。然后对剩下的元素继续上
述过程,直到全部元素有序。


Slide 59

第3章 数 组

冒泡排序法的函数代码如下:
#include
void main( )
{
int a[6]={1,7,3,22,9,5};

int i,j,t,flag;
for(i=0;i<5;i++)
{

flag=0;


Slide 60

第3章 数 组

for(j=0;j<6-i-1;j++)
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
flag=1;
}
if(flag==0) break;
}
cout<<"排序后的数组为:\n";


Slide 61

第3章 数 组

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

cout<<" "<}


Slide 62

第3章 数 组

3.6.2 查找
数组元素查找是与数组有关的另一种重要算法。有

时候需要知道一个元素在数组中的位置,即要通过元素
值找到其下标值,这就需要用到查找算法。
本节介绍两种基本的查找方法:顺序查找法和二分
查找法。顺序查找法的思路很朴素,也容易实现,但效
率不高;二分查找法的效率很高,但要求数组在查找前
已经排好序。这两种方法各有所长,可根据实际情况灵
活选用。


Slide 63

第3章 数 组

【例3-7】 顺序查找法例题。
顺序查找法的思路很简单:按顺序逐个访问数组
元素,并将其同要找的值比较,直到找到与要查找的
值相同的元素。
#include
void npFind(int DataArray[ ], int nSize,int fValue)
//其中参数DataArray[ ]为查找数组,nSize为数组长度,
fValue为要查找的值
{
int nIndex,flag=nSize; //设置flag为查找标记


Slide 64

第3章 数 组

for(nIndex=0;nIndexif(DataArray[nIndex]==fValue)
{

flag=nIndex;
break;

//退出循环

}

if(flagcout<<"元素找到了!是第 "<else
cout<<"在数组中没有要找的元素!"<}


Slide 65

第3章 数 组

【例3-8】 二分查找法例题。

在数组中的元素已经排好序的前提下,使用二分查找法可以
极大地提高查找效率。
二分查找法思路:首先假设数组已经按增序排好序。取位于

数组中间的元素同要查找的值比较,如果待查值等于这个元素的
值,则查找结束。如果待查值小于这个元素的值,则要查找的元
素肯定在数组的左半边,将数组左半边看成完整的数组,继续使

用二分查找法查找。如果待查值大于这个元素的值,则要查找的
元素肯定在数组的右半边,将数组右半边看成完整的数组,继续
使用二分查找法查找。


Slide 66

第3章 数 组

二分查找法的函数代码如下:
#include
void efFind(int DataArray[ ],int nSize,int fValue)
{
int flag=0;

//设置flag为查找标记

int nStart=0;

//开始元素下标

int nEnd=nSize-1;

//结尾元素下标

int nMid;

//二分法中间元素下标


Slide 67

第3章 数 组

while(nStart<=nEnd)
{
nMid=(nStart+nEnd)/2;

//计算中间元素下标

if(DataArray[nMid]==fValue)
{
flag=1;
break;

//标记查找成功
//退出循环

}
/*如果待查找的值大于中间元素的值,取后半边继续
查找;
否则,取前半边继续查找*/


Slide 68

第3章 数 组

if(fValue>DataArray[nMid])
nStart=nMid+1;
else
nEnd=nMid-1;
}
if(flag)
cout<<" 元 素 找 到 了 ! 是 第 "<"<else

cout<<"在数组中没有要找的元素!"<}


Slide 69

第3章 数 组

3.6.3 统计
统计也是与数组有关的另一种常用算法。当需要知道
一个元素在数组中出现的次数时,就要用到统计的算法。
本节通过两个例子介绍两种基本的统计方法:一种是
顺序查找统计法,另一种是借用数组下标值的统计方法。
实际上,统计方法很多,可根据具体情况灵活运用。


Slide 70

第3章 数 组

【例3-9】 顺序查找统计例题。
顺序查找统计,顾名思义就是按顺序逐个访问数
组元素,每找到一个要统计的元素就给计数器变量加1。
顺序查找的程序代码如下:
#include
void tjData(int DataArray[],int nSize,int tjValue) //顺
序查找统计函数
{

int nIndex,tjSum=0;


Slide 71

第3章 数 组

for(nIndex=0;nIndexif(DataArray[nIndex]==tjValue)
tjSum++;
if(tjSum)
cout<<"元素 "<"<else
cout<<"没有元素 "<}
#define N 10
void main( )


Slide 72

第3章 数 组

{
int a[N]={1,7,3,7,9,3,12,7,15,9};
int toFind;
cout<<"请输入欲统计的元素值:";
cin>>toFind;

tjData(a,N,toFind); //调用统计函数
}
程序运行结果为

请输入欲统计的元素值:7
元素 7共有3个


Slide 73

第3章 数 组

【例3-10】 借用数组下标值进行统计例题。
此方法是一种技巧性算法,主要借用统计元素的
一些特性(比如整除某数后的商均相等或其值就等于数
组下标等)来进行。例如,输入若干整数,其值均在
1~4的范围内,请编写程序用于统计每个整数出现的
次数。
程序代码如下:
#include
void main( )
{


Slide 74

第3章 数 组

int tj[4]={0,0,0,0};

//存放统计结果

int tjData;
cout<<"请输入数据1~4,输入其它时结束:"<cin>>tjData;
while(tjData>0&&tjData<5)

//限定数据范围的循环

{
tj[tjData-1]++;
1]作用
cin>>tjData;
};
cout<<"统计结果为:"<
//注意数组tj的下标[tjData-


Slide 75

第3章 数 组

for(int i=0;i<4;i++)
cout<<"

"<
}
程序运行结果为
请输入数据1~4,输入其它时结束:
1 2 3 4 1 2 6
统计结果:
1∶2
2∶2
3∶1
4∶1


Slide 76

第3章 数 组

3.6.4 字符处理
字符处理是C++语言的特色功能之一,在计算机水平与等级

考试中经常遇到。关于字符处理的方法很多,但最主要的还是掌
握字符数组下标的灵活运用。由于篇幅有限,这里我们仅举一例
给以示范。


Slide 77

第3章 数 组

【例3-11】

在给定的由英文单词组成的字符串中,

找出其中都包含的最长的单词(同一字母的大小写视为
不同字符)。约定单词全由英文字母组成,单词之间由
一个或多个空白符分隔。
分析:自左至右顺序扫视字符串,逐个找出单词
(单词开始位置和单词长度)。当该单词的长度比已找到

的单词更长时,记录该单词的开始位置和长度。继续
此过程直至字符串扫视结束,最后输出找到的单词。


Slide 78

第3章 数 组

程序代码如下:
#include
void main( )
{
char s[ ]="This is C programming

test.";

int i=0,pLen=0,maxLen=0,pSeat=0;
while(s[i]!='\0')
{

while(s[i]!=' '&&s[i]!='\0') //区分单词并计算长度


Slide 79

第3章 数 组
{
pLen++;
i++;

}
if(pLen>maxLen) //记录最长单词的位置与长度
{
pSeat=i-pLen;
maxLen=pLen;
}
while(s[i]==' ') i++; //跳过单词之间的空格

pLen=0; //为计算下一个单词长度赋初值
}


Slide 80

第3章 数 组

cout<<"最长的单词为:";
for(i=0;icout<cout<}

程序运行结果为
最长的单词是programming


Slide 81

第3章 数 组

3.7 构造数据类型
3.7.1 结构体
在处理实际问题时,经常会遇到由相互关联但类型不同的数
据组成的数据结构,
比如要描述某一商品的一笔销售情况,就要包括商品号、商
品名、单价、数量、金额和销售日期等数据,它们的数据类型各
不相同,但属于同一个整体,这样的数据结构在C++中称为结构
体。


Slide 82

第3章 数 组



1.结构体类型的定义

要定义描述某一问题的数据结构变量,程序员首先应从实际
问题要描述的对象出发,自己建立一个结构体类型(称为结构体类
型的定义),然后再由这个已定义的结构体类型去定义相应的变量。
定义一个结构体类型的一般形式如下:
struct <结构体类型名>
{
<类型标识符> 成员名l;
<类型标识符> 成员名2;
<类型标识符> 成员名n;
};


Slide 83

第3章 数 组

例如,对商品销售记录可定义如下结构体类型:
struct Commodity
{
unsigned long No;

//商品号

char name[20];

//商品名

float price;

//单价

int number;

//销售数量

double amount;

//销售金额

};


Slide 84

第3章 数 组

说明:
① 定义结构体类型时,使用关键字struct。结构体
类型名的命名应符合C++语言的标识符命名规则。
② 结构体中的数据成分被称为成员。成员可以是
基本数据类型,也可以是另一个诸如结构体这样的复
杂数据类型。
③ 大括号内是一个成员表,成员名可以与程序中
的变量名相同,但不能与结构体类型名相同,每个成
员的末尾以及大括号后边都要加分号。


Slide 85

第3章 数 组

④ 若同一个结构体类型要被多个源文件使用,则
经常将这些结构体类型的定义集中存放在一个头文件
中,源文件中只要用#include命令包含此头文件即可,
不必在每个源文件中重复同样的结构体类型定义。这
部分内容将在第5章详细介绍。
这里要强调的是,定义一个结构体类型只是向
C++系统通报该结构体类型的名称和各成员的组成,
C++对结构体类型并不分配内存,只有在定义结构体
变量时,C++才为结构体变量分配内存。


Slide 86

第3章 数 组



2.结构体变量的声明
结构体是一种数据类型,同基本数据类型一样,可以声

明变量、作为函数的参数等。
定义了结构体后,就可以用定义过的结构体类型声明结
构体变量了。声明结构体变量一般有两种形式,分别是:
<结构体类型名> 变量名

struct <结构体类型名> 变量名


Slide 87

第3章 数 组

声明的结构体变量将按照结构体中的各个成员按顺序在内存
中分配空间。
例如,用上面的Commodity结构体声明一个变量:
Commodity MyComputer;
则MyComputer将在内存中占用120个字节,其中No(商品号)占
32个,name(商品名)占20个,price(单价)占32个,number(销售数
量)占4个,amount(销售金额)占32个。
另外,声明结构体变量也可在定义结构体类型的同时进行,
其形式如下:


Slide 88

第3章 数 组

struct [结构体类型名]
{

<类型标识符> 成员名l;
<类型标识符> 成员名2;

<类型标识符> 成员名n;
} [变量1,变量2,…,变量n];
例如:

struct Commodity
{


Slide 89

第3章 数 组

unsigned long No;
char name[20];
float price;
int number;
double amount;

}goods1,goods2;
这里既定义了结构体类型Commodity,又定义了
结构体变量goods1、goods2,形式比较紧凑。如果以

后需要再定义新的结构体变量goods3、goods4,可以
直接用语句Commodity goods3,goods4;进行声明。


Slide 90

第3章 数 组



3.结构体变量的初始化
所谓结构体变量的初始化,就是在定义结构体变量

的同时,对它的每个成员赋初值,其语法形式与数组赋
初值非常相似:
<结构体类型> 变量名={表达式1,表达式2,…,表
达式n}
其中,n个表达式分别对应于结构体中的n个成员。


Slide 91

第3章 数 组

例如:
Commodity
3,19800};

goods1={210003,"Computer",6600,

注意:
① 表达式各类型要与结构体成员的类型对应一致。
② 只可对结构体变量在定义时进行初始化,不可
对结构体类型初始化。例如:
struct Commodity
{

unsigned long No=210003;
char name[20]= "Computer":


Slide 92

第3章 数 组

float price=6600;
int number=3;

double amount=19800;
};
是错误的。


Slide 93

第3章 数 组



4.结构体变量的引用
一个结构体变量应该以其成员为单位进行访问。依照某个

成员的数据类型,可以按照相应数据类型的操作规范进行访问,
换句话说,可以将一个结构体变量中的成员当成普通变量来使
用。访问一个结构体变量的成员的形式如下:
<结构体变量名>.<成员名>
其中,“.”称为成员运算符,它的优先级高于所有的算术运
算符、条件运算符和逻辑运算符。


Slide 94

第3章 数 组

例如,对由结构体类型Commodity定义的变量goods1、
goods2,可以进行以下操作:
Commodity goods1={210003 , "Computer" , 6600 , 3 ,
19800},goods2;
//定义结构体变量goods1、goods2,同时对
goods1进行初始化
int TotalAmount;

//定义一普通变量

goods2.No=110011;
strcpy(goods2.name,"Television");
函数strcpy给goods2的name成员赋值,

//用字符串复制


Slide 95

第3章 数 组

//注意不能用赋值语句“goods2.name="Televsion";”给
//goods2的name成员赋值
goods2.price=8000;
goods2.number=2;
goods2.amount=goods2.number*goods2.price;

TotalAmount=goods1.amount+goods2.amount;
如果一个结构体中包含另一个结构体作为成员,则访问
该成员中的成员时,要使用如下形式:

<结构体变量名>.<结构体成员名>.<成员名>


Slide 96

第3章 数 组

例如,我们仍以商品销售记录为例,对其结构体类
型增加一个销售日期成员Buydate(结构体类型):
struct Buydate

{
int year;
int month;
int day;
};
struct Commodity
{
unsigned long No;
char name[20]:


Slide 97

第3章 数 组

float price;
int number;
double amount;
Buydate date;

//此时的成员名是date,是一

结构体类型(Buydate)
}goods1;
则要访问结构体变量goods1中的二级成员year、month、
day,须用形式:

goods1.date.year; goods1.date.month; goods1.date.day;


Slide 98

第3章 数 组

另外,在此要特别说明的是,结构体变量本身不
代表一个特定的值,所以对结构体变量进行各种运算
(算术运算、比较运算、逻辑运算等)均无实际意义。但
结构体变量可以作为函数参数,同类型结构体变量之
间也可以赋值,其赋值规则是,按成员依次赋值。
例 如 , goods1 和 goods2 是 由 同 一 结 构 体 类 型

Commodity定义的,所以可以相互
赋值:
goods2=goodsl; //合法
表示将goodsl的每个成员的值赋给goods2的对应成
员,使这两个结构体变量所有成员的值完全相同。


Slide 99

第3章 数 组



5. 结构体数组
多个同一类型的结构体变量也可以用数组的形式来处

理,即结构体数组。
结构体数组在内存中的存放格式类似于普通数组,仍
然是按元素顺序排列,只不过每个元素占用的字节数一般
比普通数组要多。下面我们举例来说明其应用。


Slide 100

第3章 数 组

【例3-12】

有6个学生,每个学生的数据包括学号、

姓名、三门课的成绩,设计程序实现:
(1) 计算出每个学生的平均成绩。
(2) 将学生数据按平均成绩从高到低排序。
程序代码如下:
#include
struct student
{

int no;

//定义结构体类型


Slide 101

第3章 数 组

char name[15];
int c[3];
float aver;
};
#define N 6
void output(student a[N])

//输出学生数据函数

{
cout<<"\n

学 生 数 据 表\n\n";

cout<<"学号
绩\n";

姓名

cout.precision(4);

成绩1 成绩2 成绩3 平均成

//设定小数部分


Slide 102

第3章 数 组

for(int i=0;i{
cout<cout.width(16);

//设定输出宽度

cout<
cout.width(8);
cout<cout<<"

}
}

"<
"<
"<

Slide 103

第3章 数 组

void main( )
{
int i,j,k;
student

cs[N]={{1001,"Gao

na",98,88,76},{1002,"Wang

jianjun",95,90,88},
{1003,"Liou
yao",76,78,84},{1004,"Ma ailian",56,60,72},
{1005,"Li
ming",96,93,90},{1006,"Cheng jiantao",86,79,90}};
student temp;
for(i=0;i

Slide 104

第3章 数 组

cs[i].aver=float(cs[i].c[0]+cs[i].c[1]+cs[i].c[2])/3;
for(i=0;i{
k=i;
for(j=i+1;jif(cs[k].aver{temp=cs[i];cs[i]=cs[k];cs[k]=temp;}
构体变量直接进行交换
}

output(cs);
}

//用结


Slide 105

第3章 数 组

程序运行结果为
学生数据表
学号

姓名

成绩1 成绩2 成绩3 平均成绩

1005

Li ming

96

93

95

90

1002

Wang jianjun

1001

Gao na

1006

Cheng jiantao

1003

Liou yao

76

78

84

79.33

1004

Ma ailian

56

60

72

62.67

98

90

88
86

88

93

76
79

91

87.33
90

85