第五章 数组.docx

上传人:b****2 文档编号:20158280 上传时间:2023-04-25 格式:DOCX 页数:36 大小:38.22KB
下载 相关 举报
第五章 数组.docx_第1页
第1页 / 共36页
第五章 数组.docx_第2页
第2页 / 共36页
第五章 数组.docx_第3页
第3页 / 共36页
第五章 数组.docx_第4页
第4页 / 共36页
第五章 数组.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

第五章 数组.docx

《第五章 数组.docx》由会员分享,可在线阅读,更多相关《第五章 数组.docx(36页珍藏版)》请在冰豆网上搜索。

第五章 数组.docx

第五章数组

第五章数组

本章的重点、难点:

•理解数组的概念以及运用数组实现数据的处理与操作。

学习目标:

•学会数组(一维数组、二维数组以及多维数组)的定义。

•掌握数组与循环结构结合使用的方法。

•体会数组在处理问题时的灵活和便利。

在实际生活中,常常遇到大批量的数据处理问题,如统计班级学生某门课程的平均成绩。

这类问题的特点是数据量比较大,但是各个数据之间存在一定的内在联系。

如果使用前面学习的变量处理这些数据则非常不方便,有的问题甚至不可能只依靠简单的变量来处理解决,为了应对这类问题,C语言给出了一个概念——数组。

数组是具有相同数据类型的数据的有序集合。

数组中的每一个元素具有相同的名称。

表示数组元素的位置使用“下标”这个概念,它是数组中元素的一个索引或指示。

定义了一个数组之后,系统会在内存中提供一片连续的空间依次存放数组的各个元素。

数组下标的个数确定数组的维数,只有一个下标的数组称为一维数组,有两个下标的数组称为二维数组,以及三维、多维数组。

前面各章所使用的数据都属于基本数据类型(整型、实型、字符型),C语言除了提供基本数据类型外,还提供了构造类型的数据,它们是本章的数组类型以及将要学习的结构体类型、共同体类型。

构造数据类型是由基本数据类型的数据按照一定的规则组成,所以也称为“导出类型”。

例如:

inta[10];

定义了一个一维数组a,该数组由10个数组元素构成的,其中每一个数组元素都属于整型数据类型。

数组a的各个数据元素依次是a[0],a[1],a[2]…a[9](注意:

下标从0~9)。

每个数据元素都可以作为单个变量使用(如赋值,参与运算,作为函数调用的参数等)。

一维数组可以看作一个数列或向量。

其存储方式见图5-1所示。

又如:

floatb[3][3];

定义了一个二维数组b,该数组由9个元素构成,其中每一个数组元素都属于浮点(实数)数据类型。

数组b的各个数据元素依次是:

b[0][0],b[0][1],b[0][2],b[1][0],b[1][1],b[1][2],b[2][0],b[2][1],

b[2][2]

(注意下标顺序)。

每个数据元素,比如b[0][1]均可作为单个变量使用。

二维数组可以看作一个矩阵。

其存储方式以及矩阵方式的示意图,见图5-2。

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

a[9]

b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

b[2][0]

b[2][1]

b[2][2]

b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

b[2][0]

b[2][1]

b[2][2]

 

图5-1               图5-2

5.1一维数组

一维数组中的各个数组元素是排成一行的一组下标变量,用一个统一的数组名来标识,用一个下标来指示其在数组中的位置。

下标从0开始。

一维数组通常和一重循环相配合,对数组元素进行处理。

5.1.1一维数组的定义

一维数组的格式定义:

类型说明数组名[整型常量表达式];

例如:

inta[100];

定义了一个数组a,元素个数为100,数组元素类型为整型。

说明:

(1)数组名:

按标识符规则。

本例a就是数组名。

(2)整型常量表达式:

表示数组元素个数(数组的长度)。

可以是整型常量或符号常量,不允许用变量。

整型常量表达式在说明数组元素个数的同时也确定了数组元素下标的范围,下标从0开始~整型常量表达式-1,注意不是从1至整型常量表达式指定的数量。

C语言不检查数组下标越界,但是使用时,建议不越界使用,否则结果难以预料(在早期非保护模式的系统,如MS-DOS中,“越界”操作无论是覆盖了程序区、还是覆盖了数据区,都将导致程序的不可预知,如果覆盖到操作系统,甚至会引起系统的崩溃)。

本例数组元素个数是100个,下标从0-99。

(3)类型说明:

指的是数据元素的类型,可以是基本数据类型,也可以是构造数据类型。

类型说明确定了每个数据占用的内存字节数。

比如整型2字节,实型4字节,双精度8字节,字符1字节。

本例数组元素是整型,每个元素占2个字节,因为有100个数组元素,所以占用200字节。

(4)C编译程序为数组分配了一片连续的空间。

(5)C语言还规定,数组名是数组的首地址。

即a=&a[0];。

5.1.2一维数组的初始化

数组可以在定义时初始化,给数组元素赋初值。

数组初始化常见的几种形式:

(1)对数组所有元素赋初值,此时数组定义中数组长度可以省略。

例如:

inta[5]={1,2,3,4,5};或inta[]={1,2,3,4,5};

(2)对数组部分元素赋初值,此时数组长度不能省略。

例如:

inta[5]={1,2};

a[0]=1;a[1]=2;其余元素为编译系统指定的默认值0。

(3)对数组的所有元素赋初值0。

例如:

inta[5]={0};

注意:

如果不进行初始化,如定义inta[5];那么数组元素的值是随机的,不要指望编译系统为你设置为默认值0。

5.1.3数组元素的引用

数组元素的引用形式:

数组名[下标]

注意:

数组元素引用时,下标为整型的表达式,可以使用变量。

例5-1 引用数组元素的例子。

#include

main()

{

inta[10],b[5]={55,44,33,22,11},i;

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

a[i]=i+1;/*注:

a[i]可以赋值,i是整型变量*/

printf("%4d",a[i]);/*注:

a[i]可以被输出*/

}

printf("\n");

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

printf("%4d",b[i]);

printf("\n");

}

运行结果如下:

12345678910

5544332211

说明:

(1)引用数组元素时,下标可以是整型常数、已经赋值的整型变量或整型表达式。

(2)数组元素本身可以看作是同一个类型的单个变量,因此对变量可以进行的操作同样也适用于数组元素。

也就是数组元素可以在任何相同类型变量可以使用的位置引用。

(3)引用数组元素时,下标不能越界。

(如a[10]或者b[6]都是错误的)。

5.1.4一维数组的应用

例5-2 从键盘输入10个整型数据,找出其中的最小值并显示出来。

#include

main()

{

intj,k,a[10];

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

scanf("%d",&a[j]);

printf("\n");

k=0;

for(j=1;j<10;j++)

if(a[k]>a[j])k=j;

printf("min=%4d\n",a[k]);

}

运行情况如下:

2555-1-336673034050(输入10个数,各数字以空格隔开,以回车结束)

min=-33

说明:

本例是一个简单的应用。

请注意数组a的定义,以及为数组赋值的语句。

另外,请读者思考本例中第二个for循环语句是如何寻找到最小值的?

例5-3 采用“冒泡排序法”对任意输入的10个整数按由小到大的顺序排序。

所谓“冒泡排序法(BubbleSort)”是一种形象的比喻,在针对一系列数字进行排序时,使值大的数字逐渐向后(当然,也可以使值小的数字逐渐向后),以达到排序的目的,类似水泡上浮的过程。

那么,具体到采用数组技术编写程序,其排序思路为:

Step0(第0步):

对于即将被排序的n个数,从第一个数字开始向后,将相邻两个数进行比较(共比较n-1次),将值小的数交换到前面(将大数交换到后面),逐次比较,直到将最大的数移到最后(此时,值最大的数在最后);

Step1(第1步):

对前面n-1个数,运用同样方法,从前向后,将相邻两个数进行比较(共比较(n-1)-1次,即n-2次),将小数交换到前面(将大数交换到后面),逐次比较,直到将次大的数移到倒数第二个位置(此时次大的数在倒数第二个位置);

Step2(第2步):

对前面n-2个数,继续从前向后将相邻两个数进行比较(共比较(n-2)-1次,即n-3次),将小数交换到前面(将大数交换到后面),逐次比较,直到将第三大数移到倒数第三个位置(此时第三大数在倒数第三个位置);

……

依照上面的规律:

Stepi(第i步):

对前面n-i个数,从前向后,将相邻两个数进行比较(共比较(n-i)-1次),将小数交换到前面(将大数交换到后面),逐次比较,直到将第i+1大数移到倒数第i+1个位置;

……

Stepn-2(第n-2步):

将最后2个数,进行比较(比较1次),将大数交换到后面。

此时,所有的整数已经按照从小到大的顺序排列。

分析:

(1)从完整的过程(第0步~第n-2步)可以看出,排序的过程就是大数上浮的过程(同时也是小数沉底的过程),总共进行了n-1次,整个过程中的每个步骤都基本相同,可以使用循环实现(外循环)。

(2)从每一个步骤看,相邻两个数的比较,交换过程是从前向后进行的,操作也是相同的,所以也用循环完成(内循环)。

(3)为了便于算法的实现,使用一个一维数组存放这10个整型数据,排序的过程中,数据始终在这个数组中(不占用额外的空间),排序结束后,结果保存在此数组中。

#include

#defineN10

main()

{

inta[10],i,j,t;

for(i=0;i

scanf("%d",&a[i]);    /* 输入10个整数 */

for(i=0;i

  for(j=0;j

  if(a[j]>a[j+1]){

  t=a[j];a[j]=a[j+1];a[j+1]=t; /*交换*/

  }

for(i=0;i

printf("%d,",a[i]);    /*输出排序后的10个整数*/

}

运行情况如下:

265512-204332810323(输入10个数,各数字以空格隔开,以回车结束)

-2,0,2,6,8,10,12,55,323,4332,

思考与提示:

(1)如何对任意输入的10个整数按由大到小的顺序排序?

(2)“冒泡排序法”是典型的排序算法,读者要作到理解、记忆。

例5-4 采用“选择法”对任意输入的10个整数按由大到小的顺序排序。

“选择法”是指在待排序的一系列数字中逐个选出值大(或小)的数字以达到排序的目的。

运用数组技术,使用“选择法”进行由大到小排序的编程思路为:

Step0(第0步):

对即将被排序的n个数依次比较,保留最大值数字的下标(位置),然后将本次比较得到的值为最大的数和第0个数组元素交换位置(此时,第0个数组元素最大);

Step1(第1步):

将后面n-1个数依次比较,同样,保留最大值数字的下标(位置),然后将本次比较得到的值为最大的数与第1个数组元素交换位置(此时,第1个数组元素的值次大);

Step2(第2步):

将后面n-2个数依次比较,本轮比较将得到第三大的数字;

  ……

按照此规律:

Stepi(第i步):

将后面n-i个数依次比较,本轮比较将得到第i+1大的数字,保留该数的下标(位置),然后将该数字与第i个数组元素交换位置;

……

Stepn-2(第n-2步):

将最后面2个数字进行比较,保留数值大的数字的下标,然后将第n-1大数与第n-2个数组元素交换位置。

分析:

(1)从完整的过程(第0步~第n-2步)可以看出,选择排序(本例为由大到小)的过程就是选择数值大的数并交换到前面的过程,总共进行了n-1次,整个过程中的每个步骤都基本相同,可以使用循环实现(外层循环)。

(2)从每一个步骤看,也都是在若干个数中进行比较,搜索出数值大的数,记录其下标,并将该大数交换到它应该占有的前面的某个位置,共进行多次比较(如果需要的话,就进行一次数据交换),所以也可以使用循环完成(内层的循环)。

(3)为了便于算法的实现,使用一个一维数组存放这10个整型数据,排序的过程中,数据始终在这个数组中,算法结束后,结果在也在此数组中。

#include

#defineN10

main()

{

intb[10],i,j,t,max,max_i; /* max_i记录大数的位置 */

for(i=0;i

scanf("%d",&b[i]);

for(i=0;i

max=b[i];max_i=i;/*假设b[i]就是大数*/

for(j=i+1;j

if(b[j]>max){/*如果某个元素>当前最大值*/

max=b[j];max_i=j;/*记录其下标,并设置大数值*/

}

}

if(i!

=max_i){/*位置不同,交换大数到b[i]位置*/

t=b[i];b[i]=b[max_i];b[max_i]=t;

}

}

for(i=0;i

printf("%4d",b[i]);

printf("\n");

}

运行情况如下:

588-22-4472581035(输入10个数,各数字以空格隔开,以回车结束)

88351087552-22-44

5.2二维数组

二维数组,是指示数组元素使用双下标变量表示的数组。

二维数组的数组元素可以看作是排列为行、列的矩阵形式。

二维数组也用统一的数组名来标识,第一个下标表示行,第二个下标表示列。

下标从0开始。

5.2.1二维数组的定义

二维数组的格式定义:

类型说明符数组名[整型常量表达式1][整型常量表达式2];

例如:

inta[3][4];

说明:

(1)二维数组中的每个数组元素都有两个下标,且必须分别放在单独的“[]”内。

(2)二维数组定义中的第1个下标表示该数组具有的行数,第2个下标表示该数组具有的列数,两个下标之积是该数组具有的数组元素的个数。

(3)二维数组中的每个数组元素其数据类型相同。

二维数组的存放规律是“按行排列”。

(4)二维数组也可以看作是一个特殊的一维数组,其元素也是个一维数组。

5.2.2二维数组的初始化

二维数组的初始化的几种常见形式:

(1)分行给二维数组所有元素赋初值。

例如:

inta[2][4]={{1,2,3,4},{5,6,7,8}};

(2)不分行给二维数组所有元素赋初值。

例如:

inta[2][4]={1,2,3,4,5,6,7,8};

(3)给二维数组所有元素赋初值,二维数组第一维的长度可以省略(编译程序可计算出长度)。

例如:

inta[][4]={1,2,3,4,5,6,7,8};

或:

inta[][4]={{1,2,3,4},{5,6,7,8}};

(4)对部分元素赋初值。

例如:

inta[2][4]={{1,2},{5}};

5.2.3二维数组元素的引用

定义了二维数组后,就可以引用该数组的所有元素。

引用形式:

数组名[下标1][下标2]

例5-5 二维数组元素的引用的例子。

#include

main()

{

charmatrix[5][10];/*定义一个5行10列的数组*/

intx,y;

for(x=0;x<5;x++)/*数组赋初值*/

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

matrix[x][y]='.';

printf("Enterthecoordinate(00)-(49):

");

scanf("%d%d",&x,&y);/*读取指定坐标*/

for(;!

((y>=0&&y<=9)&&(x>=0&&x<=4));){

printf("\aInvalidValue!

!

\n");

printf("Pleaseenterthecoordinate(00)-(49):

");

scanf("%d%d",&x,&y);/*读取指定坐标*/

}

matrix[x][y]='*';/*设定指定坐标*/

for(x=0;x<5;x++){/*显示出数组值*/

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

printf("%c",matrix[x][y]);

printf("\n");

}

}

运行情况如下:

Enterthecoordinate(00)-(49):

24 (输入坐标,以回车结束)

..........

..........

....*.....

..........

..........

说明:

本例题显示指定坐标的位置。

通过阅读代码,可以观察到二维数组的元素的赋值、输出操作。

其中有一段代码是利用一个for循环来判断输入的数值是否在要求的范围之内的。

请读者自行理解。

假如输入的坐标“越界”,计算机的扬声器将会发出报警音并提示重新输入:

Enterthecoordinate(00)-(49):

50 (注意这里,坐标“越界”)

InvalidValue!

!

Pleaseenterthecoordinate(00)-(49):

思考与提示:

在使用数组时,请注意使用下标值的范围,C编译系统不会做数组边界检查,当你使用大于定义的下标值时,在语法上,不会有任何的错误。

但有可能改变或引用到别的变量,甚至是程序代码。

轻微的,只是程序结果错误,严重的话,可能导致系统崩溃。

5.2.4二维数组应用举例

二维数组的遍历访问(扫描),一般都采用双重循环处理(行循环与列循环)。

例5-6 分别计算3×3矩阵的两条对角线(主、辅对角线)上的元素之和。

#include

main()

{

inta[3][3]={1,3,6,7,9,11,14,15,17};

intsum1=0,sum2=0,i,j;

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

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

if(i==j)

sum1=sum1+a[i][j];

if(i+j==2)

sum2+=a[i][j];

}

printf("sum1=%d\nsum2=%d\n",sum1,sum2);

}

程序运行结果为:

sum1=27

sum2=29

说明:

对于行、列数相同的矩阵,主对角线(左上角至右下角)上所有元素的下标值具有行、列相等的特征;矩阵辅对角线(右上角至左下角)上所有元素的下标值具有行与列之和等于该矩阵的最大列下标值(或最大行下标值)的特征。

思考:

如何实现分别计算N×N的矩阵的两条对角线上的元素之积的算法。

例5-7 有一个3×5的矩阵,要求编程求出该矩阵所有元素中的最大值,并给出其所在的位置,即行、列号。

#include

main()

{

inti,j,r,c,max;

intb[3][5]={1,5,9,13,17,2,6,10,14,18,45,-8,22,79,4};

max=b[0][0];

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

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

if(b[i][j]>max){

max=b[i][j];

r=i;

c=j;

}

printf("max=%d,r=%d,c=%d\n",max,r,c);

}

程序运行结果为:

max=79,r=2,c=3

思考:

找出矩阵所有元素中的最小值的算法。

5.2.5多维数组

当数组元素的下标在2个或2个以上时,该数组称为多维数组。

其中以2维数组最常用。

定义多维数组:

类型说明数组名[整型常数1][整型常数2]…[整型常数k];

例如:

inta[2][3][3];

定义了一个三维数组a,其中每个数组元素为整型。

总共有2x3x3=18个元素。

说明:

(1)对于三维数组,整型常数1,整型常数2,整型常数3可以分别看作“深”维(或:

“页”维)、“行”维、“列”维。

可以将三维数组看作一个元素为二维数组的一维数组。

三维数组在内存中先按页、再按行、最后按列存放。

(2)多维数组在三维空间中不能用形象的图形表示。

多维数组在内存中排列顺序的规律是:

第一维的下标变化最慢,最右边的下标变化最快。

(3)多维数组的数组元素的引用:

数组名[下标1][下标2]…[下标k]。

多维数组的数组元素可以在任何相同类型变量可以使用的位置引用。

只是同样要注意不要越界。

5.3字符数组

字符数组:

存放字符型数据的数组。

其中每个数组元素存放的值都是单个字符。

字符数组分为一维字符数组和多维字符数组。

一维字符数组常常存放一个字符串,二维字符数组常用于存放多个字符串,可以看作是一维字符串数组。

5.3.1字符数组的定义、初始化及引用

字符数组也是数组,只是数组元素的类型为字符型。

所以字符数组的定义、初始化,字符数组数组元素的引用与一般的数组类似。

(定义时类型说明符为char,初始化使用字符常量或相应的ASCII码值,赋值使用字符型的表达式,凡是可以用字符数据的地方也可以引用字符数组的元素)。

例如:

charc1[10],str[5][10];

charc2[3]={'r','e','d'};或charc2[]={'r','e','d'};

printf("%c%c%c\n",c2[0],c2[1],c2[2]);

5.3.2字符串与字符数组

1.字符串与字符数组

字符串(字符串常量):

字符串是用双引号括起来的若干有效的字符序列。

C语言中,字符串可以包含字母、数字、符号、转义符。

字符数组:

存放字符型数据的数组。

它不仅用于存放字符串,也可以存放一般的、对一般读者看来毫无意义的字符序列。

C语言没有提供字符串变量(存放字符串的变量),对字符串的处理常常采用字符数组实现。

因此也有人将字符数组看作为字符串变量。

C语言许多字符串处理库函数既可以使用字符串,也可以使用字符数组。

为了处理字符串方便,C语言规定以’\0’(ASCII码为0的字符)作为“字符串结束标志”。

“字符串结束标志”占用一个字节。

对于字符串常量,C编译系统自动在其最后字符后,增加一个结束标志’\0’;对于字符数组,如果用于处理字符串,在有些情况下,C系统会自动在其数据后自动增加一个结束标志,在更多情况下结束标志要由程序员自己负责(因为字符数组不仅仅用于处理字符串)。

如果不是处理字符串,字符数组中可以没有字符串结束标志。

例如:

charstr

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

当前位置:首页 > 求职职场 > 社交礼仪

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1