数组类型是构造型数据类型之一,数组是变量的一个有序集合,其中所有的变量都具有同一种类型。例如:一个向量可以表示为由若干实数变量组成的数组;一个矩阵可以表示为由若干向量组成的数组。
数组的基础类型称为元素类型,可以是任意类型(包括以前讲的简单类型,以及后面将要讲的结构体、共用体、指针以及正在讲的数组等类型)
数组类型的构造方法是把固定数目的元素类型的数据顺序排成一个表。每个数据是元素类型的一个值。所有元素值顺序排成的表是数组类型的一个值。
数组类型的每个元素都有一个唯一的编号,称为“下标”。
数组声明
在C语言中声明数组变量使用数组声明符。一维数组的声明符结构如下:
<标识符>[<常量表达式>]
(1)标识符是要声名的数组的名字,即数组变量的名字
(2)常量表达式是要给出要声明的数组的尺寸,即相应的数组有多少个元素组成
(3)数组声名符所在的变量声名中的类型说明符指出数组的类型,也是数组中每一个元素的类型
注意:数组类型变量与已学过的简单类型变量之间的区别。简单类型变量只表示一个单值(有时也被称为简单变量),而数组类型变量则表示一组值,它由一组变量组成。
下标表达式
访问数组变量的某一个值,使用下标表达式,下标表达式的形式如下:
<数组变量>[<表达式>]
(1)数组变量指出访问哪个数组元素
(2)方括号中的表达式的类型必须是整数类型,它具体指明访问的是数组中的哪一个元素。
下标表达式实际上是一个变量,它是相应数组元素类型的一个变量。在程序中,该变量的地位、作用与相应数组元素类型的一般变量的地位、作用完全相同。凡是可以使用数组元素类型变量的地方都可以使用下标表达式,有时也称下标表达式为“下标变量”。
数组操作
(1)赋值
C不允许对数组进行整体赋值。数组赋值必须通过其元素实现。
例如:把数组t0送入数组w中
for(int m=0;m<9;m++)
{
w[m]=t0[m];
}
而不能写成w=t0
(2)运算
C也不允许在数组上进行任何操作。数组的运算必须通过其元素实现
例如求数组t0、t1的差送入数组w中,应写成
for(int m=0;m<=9;m++)
{
w[m]=t0[m]-t1[m];
}
而不能写成w=t0-t1
(3)I/O
数组变量不能作为I/O函数的实在参数,也就是说不能整个“读入”一个数组,也不能整个“输出”一个数组。以下语句都是错误的:(w为一个数组)
scanf(“%f”,&w)
printf(“%f”,w)
若想读入一批数据送入数组w中或想把w中的数据全部输出,可以分别用如下的程序来实现:
for(int i=0;i<=9;i++)
{
scanf("%d",&w[i]);
}//输入数组的变量
for(int i=0;i<=9;i++)
{
printf("%d",w[i]);
}//输出数组变量
多维数组
二维数组
二维数组的声明如下:
<标识符>[<常量表达式>][<常量表达式>]
二维数组的下标表达式如下:
数组变量[表达式1][表达式2]
多维数组
多维数组的声名符形式如下:
数组标识符[常量表达式1][常量表达式2]......[常量表达式n]
多维数组的下标表达式形式如下:
数组变量[表达式1][表达式2].....[表达式n]
数组的初值
一维数组
一维数组的初始化算子形式是一对花括号“{”,“}”括起来的常量表达式表,各个常量表达式间用逗号分隔,例如:
int a[5]={0,1,2,3,4}
声名5个元素的int类型数组a,并且a中各个元素的初值分别是0,1,2,3,4
多维数组
二维数组的初始化算子形式是由一对花括号“{”,“}”括起来的一维数组初始化算子表。各个一维数组初始化算子间用逗号分隔。例如:
int a[3][5]={{0,1,2,3,4},{1,2,3,4,5},{2,3,4,5,6}};
三维数组的初始化算子形式是由一对花括号“{”,“}”括起来的二维数组初始化算子表。各个一维数组初始化算子间用逗号分隔。
四维数组的初始化算子形式是由一对花括号“{”,“}”括起来的三维数组初始化算子表。各个一维数组初始化算子间用逗号分隔。
以此类推。
数据个数与数组长度不一致
在对数组进行初始化时,初始化算子中的数据个数可以与数组长度不一致。比如
(1)若数据个数小于数组长度,则数组中剩余元素填0,例如
int a[5]={1,2}
则数组a中各个元素的初值分别是1、2、0、0、0
(2)若数据个数大于数组长度,则将剩余数据丢掉,例如
int a[5]={1,2,3,4,5,6,7,8,9}
则数组a中各个元素的初值分别是1、2、3、4、5,剩余数据6、7、8、9被丢掉
数组的长度为空
使用数组的初始化,数组声名的最外层一维可以不指明本维元素个数,而由初始化算子中的元素个数决定,例如:
int a[]={0,1,2}
声名的一维数组a有3个元素(虽然在声明中没有指出a的长度),初值分别为0、1、2
int b[][4]={{0,1,2,3},{1,2,3,4},{2,3,4,5}}
声明的二维数组b,b有3行(虽然在声明中没有指出b数组有几行),每行有4个元素。
注意:在多维数组声名中,只有外层的一维长度可以省略
int a[3][]=......
int b[][][4]=....
int c[2][][5]=....
都是错误的
字符串(字符数组)
字符数组的声明显示是:
char 名[长度]
如下声明一个字符数组变量name可以保存一个人的名字:
char name[20]
"\0"是字符串结束符,表示字符串的结束。一串字符后边缀以结束符“\0”,称为“字符串”。
字符数组与字符串有着密切的联系,在C中通常用字符数组保存字符串。若不确切的讲,可以说字符数组与字符串是一个概念。在C中,用字符数组保存并且处理字符串,即把字符串作为字符数组来处理,反之字符数组也被当做字符串来处理。也可以认为字符串是常量字符数组,字符数组是字符串变量。
结束标志
为了标志字符串的结尾,C规定了一个字符串结束符“\0”。以字符“\0”作为结束符,标志字符串的结束。
C系统对字符串常量自动加一个结束符“\0”。例如:“C programing”一共有13个字符,则系统会自动用14个字符空间来保存它,前13个位置保存有效字符,最后一个位置保存结束符“\0”
结束符“\0”的ASCII码值为0,是一个不可显示字符,代表“空”。它在字符串结束处只起标志性作用,不起任何操作。
给字符串加结束符标志“\0”很重要,如果没有结束标志,会使字符串中的有效字符部分与其余无效字符混杂。对于常量字符串,系统会自动添加结束标志;对于变量字符串(字符数组),程序员必须在程序中自己添加结束标志
初始化
(1)char a[5]={‘a’,‘b’,‘c’,‘\0’}
(2)char a[5]="abc"
(3)char a[]={‘a’,‘b’,‘c’,'\0'}
(4) char a[]="abc"
I/O
在格式化I/O中,C用格式符%s控制字符串的输入输出。把%s用在printf和scanf函数的格式串中,可以直接控制输入或输出一个字符串。且字符串以字符“\0”为结束字符。
例如:
char st[16];
scanf("%s",st);
printf("%s",st);
把st中保存的字符串输出,并且以“\0”为结束符。
运算
C没有定义字符串上的运算,也不提供可施加于字符串上运算的运算符,C的字符串运算都是通过函数实现的。C有一个字符串运算函数库,标准头文件是string.h。在string.h中有这些函数的函数原型,包括关系运算、赋值运算等函数。这些函数都不涉及字符串的长度
(1)关系运算
按照字典顺序比较两个字符串使用函数strcmp。strcmp的原型是
int strcmp(const char * st1,const char * st1)
返回值如下:
- 如果字符串st1的值大于st2,函数返回一个正数
- 如果字符串st1的值等于st2,函数返回0
- 如果字符串st1的值小于st2,函数值返回一个负数
(2)赋值运算
字符串赋值操作,即把一个字符串赋值给另一个字符数组(一个字符数组变量),使用函数strcpy
strcpy函数原型是
char * strcpy(const char *st1,const char *st2)
其操作是把字符串st2的内容复制给字符串st1,覆盖st1中原有的内容。
(3)关于运算符
- 在字符串上不允许进行+、-等四则运算
- 赋值运算绝对不能直接使用赋值运算符“=”
例如:s、st为两个字符数组,s=st的意义是将st的地址送入变量s中,并不是将st的数组内容赋给s中
3、比较两个字符串的大小等的关系运算也绝对不能直接使用关系运算操作符
==、!=、<、>、<=、>=
这些关系运算符用于比较两个字符串的地址值的大小关系。