第六章 数组
6.1 一维数组
6.1.1 数组的定义
一维数组是指只有一个下标的数组:说明形式为:
<存储类型> <数据类型> <数组名>[<常量表达式>]
存储类型是指auto,register,static,extern
数据类型可以是任何一种基本数据类型或构造数据类型。
6.1.2 一维数组的引用
C语言中规定了数组必须逐个元素引用,而不能整体引用。
数组的越界操作,相当于内存访问越界,这种错误所造成的结果是无法估计的,
引用数组元素时,一定要仔细处理下标,防止出现数组越界的问题。
6.1.3 一维数组的初始化
1. 局部数组不初始化:对于普通局部数据,若定义时没有初始化,则数组中元素的值是不确定的。
2. static数组不初始化:数组中元素的默认值为0.
3. 全局数组不初始化:默认0.
4. 全部初始化:数组在定义时进行初始化,如:int a[10] = {1,2,3,4,5,6,7,8,9,10};
5. 部分初始化:当{}中值的个数少于元素个数时,只给前面部分元素赋值。
例如,如下定义就是只给数组的前5个数据初始化,而后5个数据自动赋0. int a[10] = {1,2,3,4,5};
6. 数组全部赋值
若想要对数组中的元素全部赋值,则可以省略数组下标中的常量。编译器会根据初始化数列表自动计算数组元素的个数。
如:int a[] = {1,2,4,5,6};
7. 数组全部初始化为0:int a[10] = {0};
6.1.4 一维数组的内存分配
1. 数组名代表数组的起始地址,是地址常量,对数组名求sizeof,可以得出数组占用的总空间。
2. 计算数组的元素个数:数组的元素个数 = size(数组名)/sizeof(数据类型)
6.1.5 一维数组程序举例
1. 冒泡排序
#include <stdio.h>
#define N 10
int main(int argc, char **argv)
{
int a[N],i,j,t;
printf("please input %d numbers:", N);
for(i=0; i<N; i++)
{
scanf("%d", &a[i]);
}
for(i=0; i<N-1; i++)
{
for(j=0; j<N-1-i; j++)
{
if(a[j]>a[j+1])
{
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
printf("The array after sort:\n");
for(i=0; i<N; i++)
{
printf("%5d", a[i]);
}
printf("\n");
return 0;
}
2. 选择排序
3. 其他排序算法
快速排序(Quick Sort)
插入排序(Insertion Sort)
归并排序(Merge Sort)
堆排序(Heap Sort)
选择排序(Selection Sort)
拓扑排序(Topological Sort)
希尔排序(Shell Sort)
桶排序(Bucket Sort)
计数排序(Counting Sort)
基数排序(Radix Sort)
6.2 多维数组
6.2.1 多维数组定义及初始化
1. 多维数组定义 <存储类型> <数据类型> <数组名><常量表达式1><常量表达式2>...<常量表达式n>
多维数组与一维数组相比,只是增加了多个下标。
二维数组定义: <存储类型> <数据类型> <数组名>[常量表达式1][常量表达式2] 其中常量表达式1表示行数,常量表达式2表示列数。
2. 二维数组初始化
1. 按行赋初值,每一组的初始值都用{}括起来。
int a[2][3] = {{1,2,3}, {4,5,6}}; 全部进行了初始化
int b[2][3] = {{1}, {4,5}}; 初始化了部分元素
2. 按线性存储的方式给二维数组赋初值
int a[2][3] = {1,2,3,4,5,6};
3. 可以省略左边下标范围的方式,给二维数组赋初值。
int a[][3] = {{1,2,3},{4,5,6}};
6.2.2 二维数组的内存分配
按行优先存,存储了第一行的元素,再存第二行的,以此类推。
6.2.3 深入理解二维数组
int a[2][3];
------------------------------------------
0xff58a90 | int a[0][0] 地址单位是字节
--------------------|----------------------
0xff58a94 | int a[0][1]
--------------------|----------------------
0xff58a98 | int a[0][2]
--------------------|----------------------
0xff58a9c | int a[1][0]
--------------------|----------------------
0xff58a90 | int a[1][1]
--------------------|----------------------
0xff58a94 | int a[1][2]
-------------------------------------------
1. a是二维数组名,是地址常量。
2. a[0]a[1]a[2]实际是一维数组名,代表一维数组的起始地址,是地址常量。
3. a+1和a的地址差12个字节,相当于3个数组元素。因此,a代表第一行的地址,a+1代表第二行的地址。
4. a[0]+1和a[0]相差4个字节,相当于1个数组元素,因此a[0]+1相当于元素&a[0][1],a[1]+1相当于元素&a[1][1]
6.2.4 二维数组程序举例
6.3 字符数组
1. 字符数组定义
字符数组的定义形式如下:char c[5] char ch[2][3]
2. 字符数组初始化
1. 逐个为数组元素赋值
char ch[6] = {'a','b','c','d','e','\0'};
2. 使用字符串常量来为数组元素赋值
char ch[6] = {"abcde"};
char ch[6] = "abcde";
char ch[] = "abcde";
3. 注意:字符串以"\0"结尾,内存访问不能越界。
6.4 字符串
6.4.1 字符串的定义
1. 字符串是指以“\0”作为结束字符的一组字符,在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。
2. 可用下面的方式声明字符串:
char a[] = {'a','p','p','l','e','\0'};
char b[] = {"apple"};
char c[] = "apple";
由于采用了'\0'标志,所以在用字符串赋值时,经常省略数组的长度。
6.4.2 字符串的输入输出
char s1[] = "hello world";
char s2[];
1. 使用printf函数输出:printf("string1:%s\n", s1);
2. 使用scanf函数输入:scanf("%s", s2); scanf的输入项必须以地址方式出现,数组名代表了数组的首地址,不需要加取地址符号。
6.4.3 字符串处理函数
1. 字符串拷贝函数 strcpy
2. 字符串连接函数 strcat
3. 字符串比较函数 strcmp
4. 求字符串长度函数 strlen
5. 字符串分解函数 strtok