目录
0 前言
数组是指一系列同一类型数据的集合,C语言中,为了方便操作和管理数据,通常会将同一种类型的多个数据按照一定的形式和顺序组织成有序集合,这些有序数据集合被称为数组。
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一 个数组变量,比如 numbers,然后使用 numbers[0]、numbers[1]、...、numbers[99] 来代表一个个单独的变量。
数组中的特定元素可以通过索引访问。 所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。、
1 声明数组
在 C 中要声明一个数组,需要指定元素的类型和元素的数量,如下所示:
type arrayName[ arraySize ];
这叫做一维数组。arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C 数据类型。例 如,要声明一个类型为 double 的包含 10 个元素的数组 arr,声明语句如下:
double arr[10];
现在 arr 是一个可用的数组,可以容纳 10 个类型为 double 的数字
2 初始化数组
在 C 中,可以逐个初始化数组,也可以使用一个初始化语句,如下所示:
//方法一:只声明,后续赋值
double arr[5];
arr[0] = 1000.0;
arr[1] = 2.0;
...
arr[4] = 50.0;
//方法二:声明并赋值
double arr[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
注意:大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目
如果省略掉了数组的大小,数组的大小则为初始化时元素的个数:
double arr[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
所有的数组都是以 0 作为它们第一个元素的索引,也 被称为基索引,数组的最后一个索引是数组的总大小减去 1。以下是上面所讨论的数组的的图形表示:
2.1 部分初始化
数组部分初始化指的是只对数组一部分元素进行初始化,例如:
int a[5]={1,2,3};
只对前3个元素初始化,系统会自动将剩下的元素初始化为 0
3 访问数组元素
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:
double arr[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double salary = arr[3];
上面的语句将把数组中第 4 个元素的值赋给 salary 变量
4 修改数组元素
方法与单独赋值相同
a[0] = 10;
5 计算数组长度(size of)
之前我们给大家介绍过如何使用sizeof计算一个类型占用的字节数,同理我们也可以通过sizeof 计算数组占用的字节数,以及使用sizeof计算数组的长度
#include <stdio.h>
int main(void)
{
int arr[] = { 1, 2, 3, 4, 5 };
printf("arr[1]占用的字节数为%d\n", sizeof(arr[1]));
printf("arr占用的字节数为%d\n", sizeof(arr));
printf("arr数组的长度%d", sizeof(arr) / sizeof(arr[1]));
return 0;
}
运行结果:
arr[1]占用的字节数为4
arr占用的字节数为20
arr数组的长度5
5.1 应用:遍历数组
#include <stdio.h>
int main(void)
{
int arr[] = {1, 2, 3, 4, 5};
int len = sizeof(arr) / sizeof(arr[1]);
for (int i = 0; i < len; i++)
{
printf("数组第%d项的值为:%d\n", i + 1, arr[i]);
}
return 0;
}
6 定义使用数组时常见的错误
错误1、数组定义时可以不初始化,但是必须指定数组长度
错误写法
#include<stdio.h>
int main()
{
int a[];
a[0] = 10;
printf("%d\n", a[0]);
return 0;
}
正确写法
#include <stdio.h>
int main()
{
int a[5];
a[0] = 10;
printf("%d\n", a[0]);
return 0;
}
错误2、定义数组的时候,[ ]中只能是常量或常量表达式,不能是变量
错误写法
#include <stdio.h>
int main()
{
int n = 5;
int a[n];
a[0] = 10;
printf("%d\n", a[0]);
return 0;
}
正确写法
#include <stdio.h>
int main()
{
int a[5];
a[0] = 10;
printf("%d\n", a[0]);
return 0;
}
错误3、定义数组的时候,如果 “{ }”中没有初始化数据,编译就会报错
错误写法
#include<stdio.h>
int main()
{
int a[5] = { }; // 出错程序
printf("%d\n", a[0]);
return 0;
}
正确写法
#include<stdio.h>
int main()
{
int a[5] = { 10 };
printf("%d\n", a[0]);
return 0;
}
错误4、数组越界访问
数组越界访问指的是,访问数组元素超过了数组的有效作用范围,将会得到预期之外的数据
错误写法
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
printf("%d\n", a[6]);
return 0;
}
正确写法
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
printf("%d\n", a[4]);
return 0;
}
7 选择排序和冒泡排序(拓展)
7.1 选择排序
通过比较首先选出最小的数放在第一个位置上,然后在其余的数中选出次小数放在第二个位置上,依此类推,直到所有的数成为有序序列
#include <stdio.h>
int main(void)
{
int arr[] = { 9, 8, 7, 6, 5, 4 };
int len = sizeof(arr) / sizeof(arr[1]);
for (int i = 0; i < len; i++)
{
for (int j = i + 1; j < len; j++)
{
if (arr[i] > arr[j])
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
printf("排序完成后的数组:\n");
for (int k = 0; k < len; k++)
{
printf("%d ", arr[k]);
}
return 0;
}
分析:
第一轮:
9 8 7 6 5 4
8 9 7 6 5 4
7 9 8 6 5 4
6 9 8 7 5 4
5 9 8 7 6 4
4 9 8 7 6 5 4放在了正确的位置
第二轮:
9 8 7 6 5
8 9 7 6 5
7 9 8 6 5
6 9 8 7 5
5 9 8 7 6 5放在了正确的位置
第三轮:
9 8 7 6
8 9 7 6
7 9 8 6
6 9 8 7 6放在了正确的位置
第四轮:
9 8 7
8 9 7
7 9 8 7放在了正确的位置
第五轮:
9 8
8 9 8放在了正确的位置
7.2 冒泡排序
从头到尾,比较相邻的两个元素的大小,如果符合交换条件,交换两个元素的位置
每一轮比较中,都会选出一个最大的数,放在正确的位置
#include <stdio.h>
int main(void)
{
int arr[] = {9, 8, 7, 6, 5, 4};
int len = sizeof(arr) / sizeof(arr[1]);
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
分析:
第一轮:
9 8 7 6 5 4
8 9 7 6 5 4
8 7 9 6 5 4
8 7 6 9 5 4
8 7 6 5 9 4
8 7 6 5 4 9 9放在了正确的位置
第二轮:
8 7 6 5 4
7 8 6 5 4
7 6 8 5 4
7 6 5 8 4
7 6 5 4 8 8放在了正确的位置
第三轮:
7 6 5 4
6 7 5 4
6 5 7 4
6 5 4 7 7放在了正确的位置
第四轮:
6 5 4
5 6 4
5 4 6 6放在了正确的位置
第五轮:
5 4
4 5