4、数组
1、数组的定义
数组就是具有一定顺序关系的若干变量的集合。其中的每个变量,都被称为数组的元素。其中的每个交量。从定义中,我们可以看出几个关键点,首先,组成数组的元素是若干个独立的变量。其次,这些变量的数据类型必须相同。最后,变量之间有一定的顺序关系。
数组属于构造类型。一个数组可以分解为多个数组元素。这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组可分为数值数组、字符数组、指针数组、结构体数组等。
2、一维数组
2.1、一维数组的定义
定义:只一个下标的数组。
格式:<存储类型> <元素数据类型> <数组名> <[元素个数]>
一维数组定义的三种方式:
数据类型 数组名[数组长度]; 数据类型 数组名[数组长度]={值1,值2.....}; 数据类型 数组名[]={值1,值2.....};
数组名在程序中使用时表示的是数组中第一个元素的地址,也代表整个数组在内存中的首地址,他是一个地址常量。
存储类型指的是auto、register、static、extern。若省路相当于auto。
数据类型可以是任一种基本数据类型或构造数据类型。
数组名是用户定义的数组标识符。
方括号中的常量表达式表示数据元素的个数,也称为数组的长度。
对于数组的定义,这里有几点是需要特别注意的。
(1)、数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。
(2)、数组名应当符合标识符的命名规定,即由字母、数字和下划线组成, 但不能以数字开头。
(3)、数组名不能与其他变量名相同。
(4)、方括号中常量表达式表示数组元素的个数,如a[5]表示数组a有5个元素,他需要在数组定义时就确定下来,不能随着程序的运行动态更改。他的下标从0开始计数,因此5个元素分别为a[0]、a[1]、a[2]、a[3]、a[4]。
(5)、不能再方括号中用变量来表示数组的元素个数,但是可以是符号常数或常量表达式,如a[3+2]、b[5+9]。
(6)、允许在同一个类型说明中说明多个数组和多个变量。
2.2、一维数组的引用
通过下标就可以很方便地访问数组中的元素,但是,一定要注意下标从 0开始,范围为0到n-1,其中,n为元素个数。假如,引用数组元素时,下标越界了,结果将是不可预料的。ANSIC没有对使用越界下标的行为做出定义。因此,一个越界下标有可能导致以下几种结果:
(1)、若越界访问的内存空间是空闲的,程序可能不受影响,仍能正确运行。
(2)、若越界访问的空间已经被占用,且写了很重要的数据。在这种情况下,若程序执行了非法写操作则程序可能会异常终止或崩溃。
(3)、若越界访问的空间是空闲的,程序只是进行了读操作,则程序能继续运行,但无法得出正确的结果
(4)、其他情况。
我们可以看到,数组的越界操作,相当于内存访问越界,这种错误所造成的结果是无法估计的,因此,在引用数组元素时,一定要仔细地处理下标,以防止出现数组越界问题。
2.3、一维数组的初始化
数组的初始化有7种情况:
(1)、局部数组不初始化
对于普通局部数组,若定义时没有初始化,则数组中元素的值是不确定的。
(2)、static数组不初始化
对于static修饰的数组,若定义时没有初始化,则数组中元素的值默认为0。
(3)、全局数组不初始化
对于全局数组,若定义时没有初始化,则数组中元素的值默认为0。
(4)、部分初始化
在定义时,只对部分元素初始化,后面的会自动赋值为0。
如:int a[10]={1,2,3,4,5};
(5)、全部初始化1
在定义时,对数组中的元素进行全部初始化。
如:int a[10]={1,2,3,4,5,6,7,8,9,10};
(6)、全部初始化2
在定义是,省略元素的个数,对数组中的元素进行全部初始化。
如:int a[ ]={1,2,3,4,5,6,7,8,9,10};
(7)、全部初始化为0
在定义时,可以一次性把数组中的元素全部初始化为0。
如:int a[10]={0}; //他表示将数组中的所有元素都初始化为0了。
注意:数组中的元素只能单个赋值,不能整体赋值。比如,int a[9]={3};只为第一个元素赋了值。
2.4、一维数组的内存分配
数组为一个整体,数组中的元素在内存中占用一片连续的存储空间,并且根据单个元素所占存储空间来进行内存分配。
一维数组的数组名代表的是数组第一个元素的地址,也代表着整个数组的起始地址,它是一个地址常量,不可以赋值。
sizeof(数组名):他表示整个数组占用的总空间。
sizeof(数组名)/sizeof(元素数据类型):它表示数组中元素的个数。

一维数组的数组名代表的是数组第一个元素的地址,“数组名+1”表示的是下一个元素的地址; “&+数组名”表示的整个数组的地址,“&+数组名[n]”表示第n个元素的地址。


3、多维数组
一维数组只有一个下标。具有两个或两个以上下标的数组,就称为多维数组。多维数组有多个下标,以标识它在数组中的位置。
格式:<存储类型> <元素数据类型> <数组名> <常量表达式1> <常量表达式2>….<常量表达式n>
3.1、二维数组的定义
定义:具有两个下标的数组。
格式:<存储类型> <元素数据类型> <数组名> <[行数]> <[列数]>
行数表示第一维数组中元素的个数(数组的个数),列数表示第二维数组中元素的个数(元素的个数)。
二维数组定义的方式:
数据类型 数组名[行数][列数]; 数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}}; 数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4}; 数据类型 数组名[][列数]={数据1,数据2,数据3,数据4};
3.2、二维数组的初始化
(1)、降维给二维数组赋初值,即按行初始化。每一组的初始值都用{ }括起来。
例:int a[2][3]={ {7,8,9} , {6,5,4} }; //全部初始化
int a[2][3]={ {4,5} , {5} }; //部分初始化,其它元素都为0
(2)、按线性存储的形式给二维数组赋初值
例:int a[3][2]={4,5,6,7,8,9}; //全部初始化
Int a[3][2]={4,5,6}; //部分初始化,其它元素都为0
(3)、可以省略左下标的元素个数(省略行数)为二维数组赋初值。
例:int a[ ][3]={ {4,8,9} ,{5,6,3} };
注意:只能省略第一维的长度,不能省略第二维的长度。
3.3、二维数组的内存分配
二维数组在概念上是二维的,也就是说其下标在两个方向上变化,有行和列的说法。下标变量在数组中的位置也处于一个平面之中,而不是像一维数组只是一个向量。但是二维数组在内存上是按一维进行线性排序的。按行优先存储,存储了第一行,在存储第二行,依次往下类推。

二维数组的数组名表示是二维数组首个元素的地址,即第一个一维数组的地址;
“数组名[n]”表示一维数组的首个元素的地址,也表示一维数组的首地址;
“&+数组名”表示整个二维数组的地址;


4、字符数组
4.1、字符数组的定义
定义:有一定顺序关系的若干个字符型变量的集合,就是字符数组。可以是一维的,也可以是多维的。
格式:<存储类型> <字符型数据类型(char)> <数组名> <[元素个数]> //一维
<存储类型> <字符型数据类型(char)> <数组名> <[行数]> <[列数]> //二维
4.2、字符数组初始化
(1)、和普通数组一样,逐个为元素赋值
例:char a[6]={‘a’ , ‘b’ , ‘c’ , ‘d’ , ‘e’ , ‘\0’}; //字符串必须以‘\0’结束
char a[2][3]={ { ‘a’ , ‘b’, ‘\0’} , { ‘c’ , ‘d’ ,’\0’} };
(2)、使用字符串常量来为元素赋值
例:char a[8]={“abcdefg”} //字符串中隐含了‘\0’
char a[8]=“abcdefg”
char a[]=“abcdefg”
注意:字符串必须以’\0’作为结束符,在赋值时不能越界。
5、字符串
5.1、字符串的定义
定义:字符串指的是以‘\0’作为结束符的一组字符,在C语言中没有专门的字符串变量,通常用一个数组来存放一个字符串。因此当把一个字符串放入数组中时,也把结束符‘\0’存入数组,并以此作为字符串是否结束的标志。字符串必须以‘\0’结束。
格式:<存储类型> <字符型数据类型(char)> <数组名> <[]>
例: char a[ ]={‘a’ , ‘b’ , ‘c’ , ‘d’ , ‘e’ , ‘f’ , ‘g’ , ‘\0’};
char b[ ]={“abcdefg”};
char c[ ]=“abcdefg”;
用字符串赋值比用字符逐个赋值要多占一个字节,用于存放字符串结束标志’\0’。
’\0’是由编译系统自动加上的。由于采用了’\0’标志,所以在用字符串赋初值时,通常省略数组的长度。
注意:在省略数组长度时,用字符逐个赋值时必须加上‘\0’,来结束字符数组的内存占据。
5.2、字符串的输入输出
字符串的输入输出,最容易想到的方式是,使用循环语句逐个的输入输出每个字符。还可以用scanf函数和printf函数来进行字符串的输入输出。使用格式化符号“%s”,来表示处理的是字符串。scanf的各输入项必须以地址方式出现,如&a,&b,但由于数组名就代表了数组的首地址,所以只用写数组名就行了,不用再加取值符号。
printf(“%s”,数组名);
scanf(“%s”,数组名); //scanf在遇到空格、’\t’、’\n’时会认为字符串输入结束。
5.3、字符串处理函数
A、 字符串拷贝函数strcpy
|
头文件 |
#include <string.h> |
|
|
函数原型 |
char * strcpy(char *dest ,const char *src); |
|
|
参数 |
dest |
目标字符串的起始地址 |
|
src |
源字符串的起始地址 |
|
|
返回值 |
目标字符串的起始地址 |
|
|
功能 |
把字符串src拷贝到字符串dest中 |
|
|
注意 |
拷贝时,dest数组的空间必须足够大,拷贝时连“\0”一同拷贝 |
|
B、 字符串连接函数strcat
|
头文件 |
#include <string.h> |
|
|
函数原型 |
char * strcat(char *dest ,const char *src); |
|
|
参数 |
dest |
目标串的起始地址 |
|
src |
源串的起始地址 |
|
|
返回值 |
目标串的起始地址 |
|
|
功能 |
把字符串src连接到字符串dest后面 |
|
|
注意 |
连接时,dest数组的空间必须足够大,两字符串均是以‘\0’结束。连接时,字符串dest和字符串src的‘\0’都取消,新串最后加‘\0’。 |
|
C、 字符串比较函数strcmp
|
头文件 |
#include <string.h> |
|
|
函数原型 |
int * strcmp(char *s1 ,const char *s2); |
|
|
参数 |
s1 |
字符串的起始地址 |
|
s2 |
字符串的起始地址 |
|
|
返回值 |
返回比较后的结果 字符串1=字符串2,返回值=0; 字符串1>字符串2,返回值>0; 字符串1<字符串2,返回值<0; |
|
|
功能 |
按照ASCII码顺序比较字符串s1和字符串s2的大小 |
|
|
注意 |
它比较的是字符串的ASCII码值大小。 |
|
D、 字符串长度函数strlen
|
头文件 |
#include <string.h> |
|
|
函数原型 |
size_t strlen(const char *s); //size_t表示sizeof型,即数据长度 |
|
|
参数 |
s |
字符串的起始地址 |
|
返回值 |
字符串的长度(不包含‘\0’) |
|
|
功能 |
求字符串的长度(不包含‘\0’) |
|
|
注意 |
求取的字符串长度中不包含‘\0’ |
|
E、 字符串分解函数strtok
|
头文件 |
#include <string.h> |
|
|
函数原型 |
char * strtok(char *s , const char *delim) ; |
|
|
参数 |
s |
要分解的字符串 |
|
delim |
存储分割的字符串 |
|
|
返回值 |
字符串的长度(不包含‘\0’) |
|
|
功能 |
分解出的字符串的地址 |
|
|
注意 |
将字符串分解成一个个片段 |
|
[行数][列数]

浙公网安备 33010602011771号