数组学习笔记:
数组
float candy[365]; /*内含365个float类型元素的数组*/
char code[22]; /*内含22个char类型元素的数组*/
int states[50]; /*内含50个int类型元素的数组*/
[ ]表示candy,code,states都是数组,数字表明数组中的元素个数。
要访问数组可以通过数组的下标数(索引)表示数组中的各元素,数组元素是从0开始编号的
所以:candy[0] 表示candy数组的第一个元素
candy[364] 表示candy数组的第365个元素
初始化数组
int powers[8] = {1,2,3,4,5,6,7,8}; /*从ANSI C 开始支持这种初始化*/
把1赋给了数组的首元素powers[0],把2赋给了powers[1],以此类推。
在,和值之间可以使用空格。
不支持ANSI的编译器会把这种初始化识别为语法错误,在数组声明前加static可以解决问题。
打印每个月的天数
#define MONTHS 12
int days[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
有时候需要把数组设置为只读,程序只能在数组中检索值,不能写入新值。要创建制度数组,应该用const声明和初始化数组。
const int days[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
初始化列表中值少于数组元素个数时,剩余的元素都被初始化为0。
int data[4] = {111, 222 };
data[0]的值为111,data[1]的值为222,data[2]的值为0,data[3]的值为0;
初始化列表中值大于数组元素个数时,编译器会直接报错。
可以省略[ ]中的数字,让编译器自动匹配数组大小和初始化列表中的项数。
const int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
指定初始化器(C99)
eg:只初始化数组中的最后一个元素
传统C初始化语法:
int arr[6] = {0, 0, 0, 0, 0, 111};
C99规定下
int arr[6] = { [5] = 111 }; /*把arr[5]初始化为111,其他未初始化的元素都置为0*/
int day[12] = { 31, 28, [4] = 31, 30, 31, [1] = 29 };
for( i = 0; i < 12; i++)
printf("%2d, %d\n"), i+1, day[i]
在支持C99的编译器下结果为:
1 31
2 29 第一次初始化值为28,但是后面又有指定初始化语句[1] = 29, 所以之前的初始化将被最后的初始化所取代
3 0
4 0
5 31 [4] = 31, 30, 31 将arr[4] 赋值为31,紧邻着的arr[5], arr[6]赋值为30,31,后续没有说明的初始化为0
6 30
7 31
8 0
9 0
10 0
11 0
12 0
如果未指定数组元素个数,且使用了指定初始化,会怎样?
int stuff[ ] = { 1, [6] = 23 };
int staff[ ] = { 1, [6] = 4, 9, 10 };
编译器会把数组大小设置为足够装得下初始化值的值。
stuff[0] stuff[1] stuff[2] stuff[3] stuff[4] stuff[5] stuff[6] stuff数组有7个元素
1 0 0 0 0 0 23
staff[0] staff[1] staff[2] staff[3] staff[4] staff[5] staff[6] staff[7] staff[8] staff数组有9个元素
1 0 0 0 0 0 4 9 10
给数组元素赋值
声明数组后,可以借助数组下标(索引)给数组元素赋值。
/*eg 给数组元素赋值*/
#define SIZE 50
int main(void)
{
int counter, evens[SIZE];
for(counter = 0; counter < SIZE; counter++)
evens[counter] = 2 * counter;
}
C不允许把数组作为一个单元赋给另一个数组。
除了初始化以外,也不允许使用花括号{}列表的形式赋值。
#define SIZE 5
int oxen[SIZE] = { 5, 3, 2, 8 }; /*正确初始化*/
int yaks[SIZE];
yaks = oxen; /*错误,不允许*/
yaks[SIZE] = oxen[SIZE]; /*数组下标越界*/
yaks[SIZE] = {5, 3, 2, 8 }; /*不起作用,在初始化之后不能使用{}进行赋值*/
指定数组的大小
int n = 5;
int m = 8;
float a1[5]; /*可以*/
float a2[5 * 2 + 1]; /*可以*/
float a3[sizeof(int) + 1]; /*可以*/
float a4[-4]; /*不可以,数组大小必须大于0*/
float a5[0]; /*不可以,数组大小必须大于0*/
float a6[2.5]; /*不可以,数组大小必须为整数*/
float a7[(int)2.5]; /*可以*/
float a8[n]; /*C99 前不可以*/
float a9[m]; /*C99 前不可以*/
多维数组
eg:需要保存一个地方5年内每个月的降水量
step1:创建5*12 = 60个变量
step2:不如创建一个内含60个元素的数组
step3:按年份创建,创建5个数组,每个数组内含12个元素
这时我们选择使用数组的数组。主数组有5个元素(每个元素表示一年),每个元素是内含12个元素的数组(每个元素表示一个月)
float rain[5][12]; // 内含5个数组元素的数组,每个数组元素内含12个float类型的元素
如何理解?
float rain[5][12]; //先看中间粗体部分,rain[5],说明rain是一个内含5个元素的数组。每个元素是怎样的,接着看剩余部分
float rain[5][12] //float [12],每个元素是内含12个float类型元素的数组
rain[0][0] rain[0][1] rain[0][2] rain[0][3] rain[0][4] rain[0][5] rain[0][6] rain[0][7] rain[0][8] rain[0][9] rain[0][10] rain[0][11]
rain[1][0] rain[1][1] rain[1][2] rain[1][3] rain[1][4] rain[1][5] rain[1][6] rain[1][7] rain[1][8] rain[1][9] rain[1][10] rain[1][11]
....
初始化二维数组
#define YEARS 5
#define MONTHS 12
const float rain[YEARS][MONTHS] =
{
{4.3, 4.3, 3.0, 2.0, 1.2, 3.0, 4.2, 2.3, 2.0, 1.5, 1.8, 2.0 },
{4.3, 4.3, 3.0, 2.0, 1.2, 3.0, 4.2, 2.3, 2.0, 1.5, 1.8, 2.0 },
{4.3, 4.3, 3.0, 2.0, 1.2, 3.0, 4.2, 2.3, 2.0, 1.5, 1.8, 2.0 },
{4.3, 4.3, 3.0, 2.0, 1.2, 3.0, 4.2, 2.3, 2.0, 1.5, 1.8, 2.0 },
{4.3, 4.3, 3.0, 2.0, 1.2, 3.0, 4.2, 2.3, 2.0, 1.5, 1.8, 2.0 }
};
这个初始化使用了5个数值列表,每个数值列表都由{}括起来。
一个列表对应数组一行。
数值列表值和数组元素个数不匹配同之前讨论。
数值列表值 < 数组元素个数,其他的元素默认初始化为0;
数值列表值 > 数组元素个数,出错,但并不影响其他行初始化。
可以省去内部{},省去时:
数值列表值 = 数组元素个数, 正确初始化
数值列表值 < 数组元素个数,先后顺序用值初始化,后面没有值的统一默认初始化为0。