第 4章 数组从本章开始,陆续要介绍各种构造类型。在本章要为读者介绍数组类型。
4.1 一维数组
4.2 一维数组应用实训
4.3 二维数组
4.4 二维数组应用实训
4.5 字符数组与字符串
4.6 字符数组与字符串应用实训
4.1 一维数组
4.1.1 一维数组的定义在C语言中使用数组前必须先进行类型说明。
1 一维数组定义的格式为:
类型说明符 数组名 [常量表达式 ];
其中,数组名是用户定义的数组标识符,要符合标识符的命名规则。方括号中的常量表达式表示数据元素的个数,也称为数组的长度。
例如,int a[10]; 表示整型数组 a,有 10个元素。
2 数组类型定义的说明:
( 1)数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。
( 2)数组名不能与其它变量名相同。
( 3)表示数组元素的个数时可以用符号常数或常量表达式,但不能用变量或变量表达式。
( 4)允许在同一个类型说明中,说明多个数组和多个变量。
4.1.2 一维数组的引用
1 数组元素的表示形式为:
数组名 [下标 ]
其中的下标只能为整型常量或整型表达式,它表示了元素在数组中的顺序号。下标从 0开始。如为小数时,编译系统将自动取整。
例如,a[5],a[i+j],a[1+2]都是合法的数组元素。
2 使用说明
( 1)数组元素通常称为下标变量,而一维数组元素通常又称为单下标变量。
( 2)必须先定义数组,然后才能使用其下标变量。
( 3)在C语言中只能逐个地引用下标变量,而不能一次引用整个数组。
例如,输出有 10 个元素的数组必须使用循环语句逐个输出各下标变量:
for(i=0; i<10; i++) printf("%d",a[i]);
而不能用一个语句输出整个数组,如,printf(“%d”,a);是错误的:
【 例 4-1】 数组元素的引用 1
【 例 4-2】 数组元素的引用 2
4.1.3 一维数组的初始化对数组赋值,常用的有三种方法:用赋值语句对数组元素赋值、动态赋值和初始化赋值。
例如,a[0]=10;a[9]=9; 是用赋值语句对数组元素赋值
for(i=1;i<=10;i++) scanf(“%d”,&a[i]);是在程序执行过程中,对数组元素进行赋值,也称为动态赋值。
编程时如果数组元素的值已知,就可在定义数组的同时为其元素赋初值,即初始化。
1 初始化赋值的一般形式为:
类型说明符 数组名 [常量表达式 ]={表达式 1,表达式 2,……,表达式 n};
例如,int a[10]={ 0,1,2,3,4,5,6,7,8,9 }; 相当于
a[0]=0;a[1]=1...a[9]=9;
2 一维数组初始化的说明:
( 1)可以只对部分元素赋初值。当 { }中表达式的个数少于元素个数时,只给前面的元素赋值,未指定初值的元素自动取零(如果是字符数组则自动取空字符)。
例如,int a[10]={0,1,2,3,4};表示只给 a[0]~ a[4]5个元素赋值,而后 5个元素自动赋 0值。
( 2)只能对数组元素逐个赋值,不能对数组整体赋值。
例如给十个元素全部赋 1值,只能写为,int
a[10]={1,1,1,1,1,1,1,1,1,1};而不能写为,int
a[10]=1;
( 3)如不对数组进行初始化赋值,则全部元素均为 0。
( 4)在对全部元素赋初值时,可以省略数组长度。
例如,int a[5]={1,2,3,4,5};可写为,int
a[]={1,2,3,4,5}; [Return]
4.2 一维数组应用实训
【 例 4-3】 任意输入十个整数,去掉其中的最大数和最小数,求其余 8个数的平均数 。
【 例 4-4】 任意输入十个整数,按从高到低的次序排序输出 。
选择排序的基本思想是:首先从要排序的数中选择最大的数,将它放在第一个位置,然后从剩下的数中选择最大的数放在第二个位置,如此继续,直到最后从剩下的两个数中选择最大的数放在倒数第二个位置,剩下的一个数放在最后位置,完成排序 。
[Return]
4.3 二维数组
( 1)二维数组定义的格式为:
( 2)类型说明符 数组名 [常量表达式 1][常量表达式 2]… ;
其中,常量表达式 1表示第一维下标的长度,常量表达式 2 表示第二维下标的长度。
例如,int a[3][4]; 定义了一个三行四列的整型数组,
数组名为 a,其元素(下标变量)有 12个( 3× 4)。
下标 0开始,其中行下标的最大值为 2,列下标的最大值为 3,即:
a[0][0],a[0][1],a[0][2],a[0][3]
a[1][0],a[1][1],a[1][2],a[1][3]
a[2][0],a[2][1],a[2][2],a[2][3]
在C语言中,
二维数组是按行排列的,如图 4-1。
先存放 a[0]行,再存放 a[1]行,最后存放 a[2]行。每行中的四个元素也是依次存放。
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
a[1][2]
a[2][1]
a[2][0]
a[1][3]
a[2][2]
a[2][3]
4.3.2 二维数组的引用二维数组元素的表示的形式为:
数组名 [下标 ][下标 ]
其中下标应为整型常量或整型表达式。例如:
a[3][4]。
使用数组时,一定要注意数组定义和下标变量的区别。
数组定义的方括号中给出的是某一维的长度,即可取下标的最大值; 而数组元素中的下标是该元素在数组中的位置标识。前者只能是常量,后者可以是常量,变量或表达式。
4.3.3 二维数组的初始化二维数组初始化与一维数组初始化类似,也是在类型定义时给各下标变量赋以初值。
1 二维数组初始化的方法:
二维数组的初始化可按行分段赋值,也可按行连续赋值。
例如:对数组 a[5][3]:
( 1) 按行分段赋值可写为
int a[5][3]=
{{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};
( 2) 按行连续赋值可写为:
int a[5][3]={80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};
这两种赋初值的结果是完全相同的。
2 二维数组初始化赋值的说明:
( 1)可以只对部分元素赋初值,未赋初值的元素自动取 0。
( 2)如对全部元素赋初值,则可以省略第一维的长度;如以按行分段方式赋值,
即便只给出了部分元素的值,也可以省略第一维的长度。
( 3)可以将二维数组当作多个特殊的一维数组,因它的元素又是一个一维数组。
数组是一种构造类型的数据。 二维数组可以看作是由一维数组的嵌套而构成的。
[Return]
4.4 二维数组应用实训
【 例 4-5】 将一个二维数组行和列元素互换,
存放到另一个二位数组中
【 例 4-6】 某班有 30个人,每个人有 4门课的考试成绩 。 求全班单科的平均成绩和各科总平均成绩 。
[Return]
4.5 字符数组与字符串
4.5.1 字符数组的定义用来存放字符数据的数组称为字符数组。字符数组中每个元素存放一个字符。
字符数组类型定义的形式与前面介绍的数值数组类似,下标仍从 0开始。
例如,char c[10]; 定义了字符数组 c,包含
c[0]~ c[9]十个元素,即十个字符型下标变量。
C语言中同样允许使用二维字符数组或多维字符数组。
例如,char c[5][10]; 即为二维字符数组。
4.5.2 字符数组的初始化字符数组也允许在类型定义时作初始化赋值。
例如,char c[10]={ 'c',' ','p','r','o','g','r','a','m'};赋值后各元素的值为:
( 1)当对全体元素赋初值时也可以省去长度说明。
例如,c[]={'c',' ','p','r','o','g','r','a','m'};这时 C数组的长度自动定为 9。
在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。把一个字符串存入一个数组时,
也把结束符‘ \0’存入数组,并以此作为该字符串是否结束的标志。
( 2)C语言允许用字符串常量对数组作初始化赋值。
例如,char c[]={'c',' ','p','r','o','g','r','a','m'};
可写为,char c[]={"C program"};
或去掉 {}写为,char c[]="C program";
4.5.3 字符数组的引用可以通过引用字符数组中的一个元素,得到一个字符。
【 例 4-7】 字符串的输出分析:本例的二维字符数组由于在初始化时全部元素都赋以初值,因此一维下标的长度可以不加以说明。
4.5.4 字符数组的输入输出
1 字符数组的输入输出有两种方法:
( 1)以格式符“% c”逐个字符输入或输出。如例 4-7
( 2)以格式符“% s”将整个字符数组中的字符串一次输入或输出。
2 字符数组的输入输出的说明
( 1) 对一个字符数组,如果不作初始化赋值,则必须说明数组长度。
( 2) 当用 scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符。
( 3)在C语言中规定,数组名代表该数组的首地址。
scanf函数中的输入项如果是字符数组名时,就不必再加地址符 &。如例 4-8中出现的 scanf(“%s”,st);
C[0] C[1] C[2] C[3] C[4] C[5] C[6] C[7] C[8] C[9]
4.5.5 字符串处理函数
C语言提供了丰富的字符串处理函数,使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件,stdio.h”;使用其它字符串函数则应包含头文件,string.h”。
1 字符串输出函数 puts
格式,puts (字符数组名 )
功能:把字符数组中的字符串输出到显示器。 即在屏幕上显示该字符串
① puts函数中可以使用转义字符,因此输出结果成为两行。 puts函数完全可以由 printf函数取代。当需要按一定格式输出时,通常使用 printf函数。
② 在输出时字符串结束标志 '\0'转换成 '\n',即输完字符串后执行换行。
2 字符串输入函数 gets
格式,gets (字符数组名 )
功能:从键盘上输入一个字符串常量到字符数组中,
并得到一个函数值,即为该字符数组的首地址。
gets函数并不以空格作为字符串输入结束的标志,而只以回车作为输入结束。这是与 scanf函数不同的。
使用说明:
( 1) puts,gets函数每次只能输出一个字符串。例如,puts(st1,st2);或 gets(st1,st2);则都是错误的。
( 2) puts函数,gets函数完全可以由 printf函数、
scanf函数所替代,因 printf函数,scanf函数的功能更强。
3.字符串连接函数 strcat
格式,strcat (字符数组名 1,字符数组名 )
功能:把字符数组 2中的字符串连接到字符数组 1
中字符串的后面,并删去字符串 1后的串标志
,\0”。本函数返回值是字符数组 1的首地址。
4 字符串拷贝函数 strcpy
格式,strcpy (字符数组名 1,字符数组名 2)
功能:把字符数组 2中的字符串拷贝到字符数组 1
中。串结束标志 "\0"也一同拷贝。字符数名 2,
也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。
5 字符串比较函数 strcmp
格式,strcmp(字符数组名 1,字符数组名 2)
功能:对两个字符串自左向右逐个字符进行比较(按照 ASCII码顺序比较),直到出现不同的字符或‘ \0’为止。如果完全相同,
则函数值为 0,否则,以第一对不相同的字符的比较结果为两个字符串的比较结果,
函数值或者为负数或者为正数。
6 测字符串长度函数 strlen
格式,strlen(字符数组名 )
功能:测字符串的实际长度 (不含字符串结束标志 '\0') 并作为函数返回值。 [Return]
4.6 字符数组与字符串应用实训
【 例 4-10】 输入五个国家的名称按字母顺序排列输出。
分析:本程序的第一个 for循环中,利用 gets
函数输入五个国家名。由于C语言允许把一个二维数组按多个一维数组处理,因此在 gets函数中使用 cs[i]是合法的。第二个 for循环利用改进的选择排序法将各个国家名相应的字符串按字母顺序排序,并在最后进行输出。
[Return]