C语言程序设计课件 第5章_第1页
C语言程序设计课件 第5章_第2页
C语言程序设计课件 第5章_第3页
C语言程序设计课件 第5章_第4页
C语言程序设计课件 第5章_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章数组5.1一维数组5.2二维数组与多维数组5.3字符数组5.4数组的综合示例本章小结

C语言提供了多种数据类型,除了前面介绍的整型、实型和字符型等基本数据类型外,还有一些扩展的数据类型,如数组、指针、结构等。由于它们是由基本数据类型按一定规则组成的,所以被称为复合数据类型或构造数据类型。

5.1一维数组

一维数组是最简单的数组,数组元素只有一个下标。5.1.1一维数组的定义及引用1.一维数组的定义在C语言中,与变量的定义一样,数组也遵循“先定义后使用”的原则。一维数组的定义格式为类型说明符数组名[常量表达式];

例如:

shortscore[8];

表示定义一个数组,数组名为score,共有8个元素,每个元素的数据类型均为短整型。

当定义了一个数组之后,C编译程序会为所定义的数组在内存中开辟一串连续的存储单元,本例定义的score数组在内存中的排列如图5-1所示。

图5-1数组在内存中的排列

在定义一维数组时,应注意以下几点:

(1)类型说明符用来说明数组元素属于何种数据类型,如int、char、float或double等。

(2)数组名由用户自定义,与变量名的命名一样,遵循标识符命名规则。

(3)数组名后必须用“方括号”括起常量表达式,不能用其他括号。

(4)常量表达式定义数组的长度,表示数组的元素个数。

(5)常量表达式中一般包括整型常量、字符常量或符号常量,但不能包括实型(符号)常量或字符串(符号)常量。

(6)常量表达式中不能包括变量。

(7)数组元素的下标从0开始,上例定义的数组的8个元素分别是score[0]、score[1]、score[2]、score[3]、score[4]、score[5]、score[6]和score[7]。注意最大下标是7而不是8。

(8)相同类型的数组、变量可放在一起定义,中间用逗号隔开。

2.一维数组的引用

C语言规定数组不能以整体形式参与各种运算。参与各种运算的只能是数组元素,即

在程序中不能一次引用整个数组而只能逐个引用数组元素。一维数组元素的引用形式为

数组名[下标]

其中,下标可以是整型常量、整型变量或整型表达式。

数组元素与普通变量的表现形式不同,但实质是相同的,它也是一种变量。因此,一个数组元素可以像普通变量那样参与赋值、算术运算、输入和输出等操作。下面介绍一维数组的输入、输出操作,以便读者熟练掌握一维数组元素的引用。

1)一维数组的输入

我们可以在程序运行期间用赋值语句或从键盘输入语句scanf()为数组元素赋值。一般用一个循环语句来赋值。例如:

2)一维数组的输出

一维数组的输出是指用输出语句printf()将数组的元素逐个输出。例如:

从这些示例可以看出,数组元素是一种带下标的变量,它跟普通变量一样参与赋值、输入和输出等操作。但是,绝对不能把“数组名”当成变量一样使用。例如,定义

inta[100];

intb[10]={1,2,3,4,5,6,7,8,9,10};

后,采用如下语句进行数据输入输出操作:

scanf("%d",&a);

printf("%d",b);

则是错误的,无法输入或输出整个数组。

例5-1从键盘输入10个数,将这10个数逆序输出,然后求出这10个数的和并输出。

5.1.2一维数组的初始化

数组的初始化是指在定义数组的同时为数组元素赋初始值。一维数组在定义时进行初始化的格式为

类型说明符数组名[常量表达式]={值1,值2,…,值n};

其中,大括号中的各个值依次对应数组中的各个元素。各个值之间用逗号隔开。例如,数组定义及初始化语句为

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

则有x[0]=1,x[1]=2,x[2]=3,x[3]=4,x[4]=5。

在初始化一维数组时,应注意以下几点:

(1)若“{}”中初值的个数小于数组元素个数,则只有数组的前部分元素对应获得初值,后部分没有获得初值的元素则置相应类型的默认值(如int型置整数0,char型置字符'\0',float型置实数0.000 000等)。例如,定义

intx[5]={1,2,3};

则有x[0]=1,x[1]=2,x[2]=3,x[3]=0,x[4]=0。

(2)若“{}”中初值的个数等于数组元素个数,则在数组定义时可省略元素个数,此时数组长度由{}中值的个数来决定。例如,定义

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

就相当于intx[5]={1,2,3,4,5}。

(3)若“{}”中初值的个数大于数组元素个数,则编译时会出现“toomanyinitializers”之类的错误,表示初值个数太多。例如,定义

intx[5]={1,2,3,4,5,6};

是不对的。因为初值个数6超过了定义的数组长度5。

5.1.3一维数组的应用

例5-2查找最大值。

解题思路第一个for语句逐个输入10个数到数组a中。然后把a[0]送到max中。在第二个for语句中,将a[1]~a[9]逐个与max中的数进行比较,若比max的值大,则把该数组元素送入max中,因此max的值在已比较过的数组元素中总是最大的。比较结束,输出max的值。

例5-3从键盘上任意输入10个整数,要求按从小到大的顺序显示出来。排序的方法有很多种,本例采用冒泡法。

解题思路冒泡法的基本思想:通过将相邻两个数进行比较和交换,使排序码(数值)较小的数逐渐从底部移向顶部,排序码较大的数逐渐从顶部移向底部。这就像水底的气泡一样逐渐向上冒,故而得名冒泡法。

由A[0]~A[n - 1]组成的n个数据,进行冒泡排序的过程描述如下:

首先将相邻的A[n - 1]与A[n - 2]进行比较,如果A[n - 1]的值小于A[n - 2]的值,则交换两者的位置,使较小的数上浮,较大的数下沉;接着比较A[n - 2]与A[n - 3],同样使小的数上浮,大的数下沉;依次类推,直到比较完A[1]和A[0]后,A[0]为具有最小排序码(数值)的元素,此时第一趟排序结束。

然后在A[1]~A[n - 1]区间内,进行第二趟排序,使剩余元素中排序码最小的元素上浮到A[1]。重复进行n-1趟排序后,整个排序过程结束。

5.2二维数组与多维数组

前面介绍的一维数组,它的数组元素只有一个下标,说明只用一个表示数组长度的常量表达式即可。如果一维数组的每个元素本身也是一个一维数组,则形成了一个二维数组。这时就要用两个下标来表示它的每个数组元素。多维数组是指二维及以上的数组,通常被表示为数组的数组,即一个数组的元素是其他数组。

5.2.1二维数组的定义及引用

1.二维数组的定义

二维数组的定义格式为

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

例如:

inta[3][4];

定义了一个二维数组,数组名为a,数组元素有3行4列,每个数组元素都是一个整型数据。

在定义二维数组时,应注意以下几点:

(1)类型说明符、数组名及常量表达式的要求与一维数组的相同。

(2)常量表达式1和常量表达式2各在一个方括号内,例如,定义不能写成

inta[3,4];

(3)二维数组可以看成一种特殊的一维数组,其特殊之处就在于它的元素又是一个一维数组。例如,二维数组a[3][4]可以理解为它有3个元素a[0]、a[1]、a[2],每一个元素却又是一个包含4个元素的一维数组,如图5-2所示。

图5-2二维数组a[3][4]的“组成”

(4)二维数组的元素在内存中的存放顺序为“按行存放”,即先顺序存放第一行的元素,再存放第二行的元素,依次类推,如图5-3所示。从图中可以看出,最右边的下标变化最快,最左边的下标变化最慢。这一特点也适用于二维以上的多维数组。图5-3二维数组在内存中的存放方式

2.二维数组的引用

二维数组元素的引用格式为

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

5.2.2二维数组的初始化

二维数组的初始化跟一维数组初始化一样,也有3种方法。

(1)在定义数组的同时为数组元素赋初值。

①按行对二维数组赋初值。例如:

inta[3][4]={{88,78,98,85},{86,92,76,71},{82,96,84,77}};

其初始化结果可用一个二维表表示,如图5-4所示。这种赋初值方法比较直观,即把内层的第一个大括号内的数据赋给第一行的元素,第二个大括号内的数据赋给第二行的元素,依次类推即可。图5-4二维数组的初始化

也可以用这种方法只给数组中部分元素赋初值。例如:

inta[3][4]={{88}{0,0,76}};

其初始化结果可用一个二维表表示,如图5-5所示。图5-5二维数组的部分赋值

②把所有的数据写在一个花括号里,系统按数组的“按行存放”排列次序对各个元素赋初值。例如:

inta[3][4]={88,78,98,85,86,92,76,71,82,96,84,77};

其效果也如图5-4所示。

③如果对全部元素赋初值,则在定义中可省略第一维的长度,但第二维长度不可省,例如:定义

inta[3][4]={88,78,98,85,86,92,76,71,82,96,84,77};

与定义

inta[][4]={88,78,98,85,86,92,76,71,82,96,84,77};

是等价的。这是因为系统编译器可以根据数据总个数和列数来确定行数,故行数可以缺省。

(2)在程序运行时,用赋值语句为数组元素赋值。例如:

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

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

a[i][j]=0; //常用于对所有的数组元素赋一个初始状态值

(3)在程序运行时,用输入语句为数组元素赋值。例如:

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

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

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

例5-4用二维数组保存3个班的英语成绩(每个班20人),并求每个班的平均成绩。

5.2.3二维数组的应用

例5-5上三角矩阵是指主对角线以下的元素都为0的矩阵;主对角线为从矩阵的左上角至右下角的连线。试编写程序,判断一个给定的方阵是否为上三角矩阵。

例5-6应用数组构造n为6的杨辉三角形,并输出。杨辉三角形如图5-6所示。图5-6杨辉三角形

解题思路杨辉三角形是一种在数学中非常著名的三角形排列形式。它是一个用于表示二项式系数的数列。杨辉三角形的结构特点和生成方式如下:

(1)杨辉三角形是一个下三角矩阵。

(2)第一行和第二行只有元素1。

(3)从第三行开始,每行的第一个和最后一个元素都是1。

(4)对于中间的元素,它等于上一行中两个相邻元素之和。例如,第n行的第k个元素等于上一行的第k-1和第k个元素之和。

数学表达式是:C(n,k) = C(n - 1,k - 1) + C(n - 1,k)。

5.2.4多维数组

二维数组实际上是一种最简单的多维数组。C语言允许使用高于二维的多维数组,如三维数组、四维数组甚至更高维数的数组,允许使用的数组的最大维数由不同的C编译器

决定。在实际应用中,经常用到的是一维、二维和三维数组,四维以上的数组极少使用。

多维数组的定义格式为

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

其中,维数由常量表达式的个数n来决定。若n为3,则是一个三维数组。例如:

floata[2][3][4];

定义了一个三维数组,它可以理解为,三维数组a包含2个二维数组(a[0]和a[1]),每个二维数组包含3个一维数组,而每个一维数组包含4个float型的数组元素(如a[0][0]包含a[0][0][0]、a[0][0][1]、a[0][0][2]和a[0][0][3]),如图5-7所示。图5-7三维数组a[2][3][4]的“组成”

a[2][3][4]在内存中的存放顺序,如图5-8所示。图5-8三维数组在内存的存放顺序

在多维数组中,引用数组元素时其下标个数要与维数相等。由图5-7可知,对于三维数组,引用数组元素时其下标个数应当为3,形如a[i][j][k]。若下标个数小于维数,则不能代表数组元素,而只相当于数组名,如a、a[i]和a[i][j]分别代表三维、二维和一维数组名。

引入多维数组可以使编程更为灵活,因为多维数组的每一维都可以根据实际情况的不同而赋予不同的含义,从而使多维数组能描述比较复杂的数据结构。

例5-7某年级共有4个班,每班各有30名学生,有6个科目的考试成绩。求各班每个学生的平均成绩并输出。

5.3字符数组

在字符数组中,每个元素为一个字符。例如,用一个一维的字符数组来存放字符串“Iamastudent”,字符串中的字符是逐个被存放到数组元素中的。由于字符是以ASCII码的形式存储,因此理解了数值数组后,字符数组也就很容易理解了。

5.3.1字符数组的定义及引用

1.字符数组的定义

用来存放字符型(char)数据的数组是字符数组。字符数组中的每一个元素都可以存放一个字符,因此一个字符数组不仅可以存放多个字符,也可存放字符串(字符串是含有结束标志的字符数组)。因为字符数组在存放字符串时,字符串末尾的结束符'\0'也一并存放,所以,一个字符串用一维数组来存放时,数组元素个数一定要比字符数多一个。

例如:

charc[13]="Howareyou!";

定义了一个字符数组c,存放的字符串中字符数为12,考虑还有1个字符串结束符 '\0',因此定义的数组长度不能少于13。

一维字符数组的定义格式如下:

char数组名[数组长度];

例如:

charc[7];

定义了一个名为c的长度为7的一维字符数组,c的每个元素可存储一个字符,整个字符数组可存储一个字符个数少于7的字符串。

二维字符数组的定义格式如下:

char数组名[行长度][列长度];

例如:

charstr[4][9];

定义了一个名为str的4行9列的二维字符数组,每行可存储一个字符个数少于9的字符串,一共可存储4个字符串。

二维字符数组元素存储的顺序与二维数值数组完全相同,在此不再赘述。

此外,也可用整型数组存储字符串,但会有一半的存储空间被浪费。

2.字符数组元素的引用

字符数组可以与数值数组一样,按元素引用和赋值,此时的下标形式、取值范围也与数值数组相同。

5.3.2字符数组的初始化

为字符数组元素指定初值,称为字符数组的初始化。字符数组的初始化也有两种方法:

(1)在定义的同时给数组赋初值。若提供的初值(字符)个数大于数组长度,则按语法错误处理(如编译时会出现诸如Error:Toomanyinitializersinfunctionmain之类的错误信息);若初值个数等于数组长度,则数组长度值可以省略不写;若初值个数小于数组长度,则只将这些初值字符赋给前面的数组元素,其余的元素自动置为空字符(即 '\0')。

例如,定义:

charc[8]={'G','O','O','D'};

后,数组在内存中的存放如图5-9所示(图中假设首地址为2000)。图5-9数组在内存中的存放

(2)用字符串常量对字符数组进行初始化。例如:

例5-8请编写一个程序,其功能是:将一个数字字符串转换为一个整数(不得调用C语言提供的将字符串转换为整数的函数)。例如,若输入字符串"-1688",则程序要能把它转换为整数值-1688并输出。

5.3.3字符串

在前面我们提到了字符串常量。所谓字符串常量就是用双引号括起来的一组字符。但实际上,字符串是一种字符型数组,并且这个数组的最后一个单元的值是 '\0' 。也就是说,字符串是一种以 '\0' 结尾的字符数组。这个结尾的字符 '\0' 唯一的作用就是标识字符串的结束。比如,字符串常量 "china" 地内存中的存放如图5-10所示。图5-10字符串在内存中的存放

5.3.4字符数组和字符串的输入与输出

1.字符数组的输入与输出

1)用%c格式输入/输出

用%c格式输入时,每个字符都有效。

例5-9从键盘输入一个学生姓名的全拼字母,并输出。

例5-10用%s格式改写例5-9的程序。

例5-11输入一个英文单词,若字母为小写,则将其转换为大写字母并输出。

2.字符串的输入与输出

1)字符串的输入

除了可以通过初始化使字符数组各元素得到初值外,也可以使用getchar()函数、scanf()

函数或gets()函数输入字符串(或字符数组)。

(1)逐个字符输入。

(2)整个字符串一次输入。

2)字符串的输出

字符串(或字符数组)的输出可以使用putchar()函数、printf()函数或puts()函数来实现。

(1)逐个字符输出。

(2)整个字符串一次输出。

5.3.5常用字符串处理函数

C语言提供了丰富的字符串操作函数,除了上面介绍的用于字符串输入输出的gets()和puts()函数外,还有很多其他专门的字符串操作函数,这些函数包含在头文件“string.h”中。因此,若需使用这些函数,应在程序之前加上语句:

#include<string.h>

下面介绍几种常用的字符串操作函数,这里写出这些函数实现的参考程序作为字符串操作的例子。

1.strlen(字符数组)

strlen(字符数组)的功能是测试字符串的长度。函数值为字符串的实际长度,不包括结束符 '\0'。

2.strcpy(字符数组1,字符数组2)

strcpy(字符数组1,字符数组2)的功能是把字符数组2中的字符串复制到字符数组1中去(即给一个字符数组赋值)。例如:

chars1[8],s2[]="GOOD";

strcpy(s1,s2);

执行后,s1数组的状态如图5-11所示。图5-11s1数组的状态

3.strcat(字符数组1,字符数组2)

strcat(字符数组1,字符数组2)的功能是把字符数组2中的字符串连接到字符数组1的字符串后面。

连接前后数组的状态如图5-12所示。

图5-12连接前后的数组状态

4.strcmp(字符数组1,字符数组2)

strcmp(字符数组1,字符数组2)的功能是对字符数组1中的字符串和字符数组2中的字符串进行比较。比较规则为:按字符ASCII的大小自左至右逐个比较两个字符串的字符,直到出现不同的字符或遇到 '\0' 为止。若全部字符相同,返回值为0;若字符串1>字符串2,则返回值为一个正数;若字符串1<字符串2,则返回值为一个负数。

5.3.6字符数组的应用

例5-12有3个字符串,要求找出其中“最大”者。

解题思路如果将两个字符进行比较,所谓“大”者是指字符的ASCII码较大的那个字符。例如,字符 'a'大于字符 'A'。如果是字符串,则从第一个字符开始一一进行比较,如果第一个字符相同,就比较下一个字符,直到出现不同为止。如果字符串中都是英文字母,有一个简单的判定方法:按英文字典的顺序,字典中位置在后的较大,例如 "girl">"boy","then"<"they"。

题目要求处理3个字符串,需要定义一个二维的字符数组(取名str),假定每个字符串不超过19个字符,则可定义二维字符数组的大小为3 × 20,即有3行20列,每一行可以容纳20个字符(包括最后的结束符 '0')。可以把str[0]、str[1]、str[2]看作3个一维字符数组,它们各有20个元素。现用gets()函数分别读取3个字符串。经过两次比较,就可得到最大者,把它放在一维字符数组string中。为叙述方便,把str[0]、str[1]、str[2]分别简称为串0、串1、串2。

例5-13输入一行字符,统计其中的单词总数,单词之间用空格分隔开

解题思路要统计输入行中的单词总数,可以定义单词为连续的非空格字符序列,并将连续的空格看作单词的分隔符。程序中,首先读取整行字符串,然后遍历每个字符。为了区分新单词的开始,可使用两个变量num和word。num(初始化为0)用来统计单词的个数,word(也初始化为0)作为标志位,指示当前是否在单词内。

遍历字符串时,若遇到空格,则将word置0,表示目前不在单词中。若当前字符不是空格并且word为0(表示上一个字符是空格或者是字符串的开始),则将word置1,并将num增加1,因为这意味着遇到一个新单词。如果当前字符不是空格且word已经为1,则继续遍历,因为这仍然是当前单词的一部分。遍历到字符串的结尾则遍历结束。最后,num变量就表示了输入字符串中的单词总数。

5.4数组的综合示例

例5-14求任意两个正整数(不超过8位)之间所有整数所包含的数字0~9出现的次数。解题思路因为输入的两个整数均不超过八位数,所以可以定义两个长整型变量来存储。通过循环将每次得到的整型数用sprintf()函数将其转换成8个字符的字符串并存放到字符数组str中,字符串不足8位时高位部分补空格字符,再对str中每个字符进行统计。数字出现的次数可以定义一个长整型数组count来表示,其大小为10,count[0]存放0出现的次数,count[1]存放1出现的次数,…,count[9]存放9出现的次数。

例5-15输入一行字符,统计其中各个大写字母出现的次数。

解题思路定义一个拥有26个int类型数组元素组成的一维数组num,用于存放26个大写字母出现的次数,num[0]存放字母 'A' 的次数,num[1]存放字母 'B' 的次数,…,num[25]存放字母 'Z' 的次数。调用库函数memset()将数组num清0。通过getchar()函数读入当前字符到ch变量中,如果是回车换行符 

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论