C语言——数组

本文详细介绍了数组的概念和使用,包括一维数组的定义、访问和初始化,强调了数组下标的正确使用和避免越界。接着,讲解了二维数组的声明、初始化方式,以及如何通过嵌套循环处理二维数组数据。最后,提到了多维数组的声明,并指出处理多维数组需使用多重循环。示例代码展示了如何计算年降雨量和月平均降雨量,进一步巩固了数组应用的理解。
摘要由CSDN通过智能技术生成

一. 一维数组

1.数组作用:数组通常被用来储存程序需要的数据。

2.构成:数组由数据类型相同的一系列元素组成。

3.数组的定义和使用:  定义数组:<类型>变量名称[元素数量] 元素数量必须为整数                     需要使用数组时,通过声明数组告诉编译器数组中内含多少元素和这些元素的类型。编译器根据   这些信息正确地创建数组。普通变量可以使用的类型,数组元素都可以用。

/* 数组声明*/ 
int main(void) 
{
 float candy[365]; /* 内含365个float类型元素的数组 */ 
 char code[12]; /*内含12个char类型元素的数组*/
 int states[50]; /*内含50个int类型元素的数组 */
 ... 
}
//方括号([])表明candy、code和states都是数组,方括号中的数字表明 数组中的元素个数。

 4.如何访问数组:要访问数组中的元素,通过使用数组下标数(也称为索引)表示数组中 的各元素。数组元素的编号从0开始,所以candy[0]表示candy数组的第1个元素,candy[364]表示第365个元素,也就是最后一个元素。

5.初始化数组:

int main(void)
{
int powers[8] = {1,2,4,6,8,16,32,64}; /* 从ANSI C开始支持这种初始化 */
...
}
如上所示,用以逗号分隔的值列表(用花括号括起来)来初始化数组, 各值之间用逗号分隔。在逗号和值之间可以使用空格。根据上面的初始化, 把 1 赋给数组的首元素(powers[0]),以此类推。
eg:演示程序:
/* day_mon1.c -- 打印每个月的天数 */ 
#include <stdio.h> 
#define MONTHS 12
int main(void) 
{
  int days[MONTHS] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 
  int index;
  for (index = 0; index < MONTHS; index++) {
  printf("Month %2d has %2d days.\n", index + 1, days[index]); }
  return 0;  
}
/*该程序的输出如下: 
Month 1 has 31 days. 
Month 2 has 28 days. 
Month 3 has 31 days. 
Month 4 has 30 days. 
Month 5 has 31 days. 
Month 6 has 30 days. 
Month 7 has 31 days. 
Month 8 has 31 days. 
Month 9 has 30 days. 
Month 10 has 31 days. 
Month 11 has 30 days. 
Month 12 has 31 days.*/

#define MONTHS 12   称为宏定义

牢记:数组元素的编号从0开始,超出称为数组下标越界!!!

6.使用 const 声明数组作用:有时需要把数组设置为只读。这样,程序只能从数组中检索值,不能把 新值写入数组。要创建只读数组,应该用const 声明和初始化数组。因此,上例 初始化数组应改成: const int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31}; 这样修改后,程序在运行过程中就不能修改该数组中的内容。
注意:如果部分初始化数组,剩余的元素就会被初始化为0。
            如果初始化列表的项数多于数组元素个数,则编译器会视为错误。
7.如果初始化数组时省略方括号中的数字,编译器会根据初始化列表中的项数来确定数组的大小。

eg: 演示程序

/* day_mon2.c -- 让编译器计算元素个数 */
#include <stdio.h> 
int main(void) 
{
  const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31 };
  int index; 
  for (index = 0; index < sizeof days / sizeof days[0]; index++) //index是数组下标的意思
  printf("Month %2d has %d days.\n", index + 1, days[index]); 
  return 0; 
}

程序解释:sizeof不是变量而是运算符,该运算符给出它的运算对象的大小(以字节为单位)。所以sizeof days是整个数组的大小(以字节为单位),sizeof day[0]是数组中第一个元素的大小(以字节为单位)。整个数组的大小除以单个元素的大小就是数组元素的个数。

8.如何给数组元素赋值:声明数组后,可以借助数组下标(或索引)给数组元素赋值。例如,下面的程序段给数组的所有元素赋值:

/* 给数组的元素赋值 */
#include <stdio.h>
#define SIZE 50 
int main(void) 
{
  int counter, evens[SIZE]; 
  for (counter = 0; counter < SIZE; counter++) 
  evens[counter] = 2 * counter; 
  ... 
}
注意: 这段代码中使用循环给数组的元素依次赋值。 C 不允许把数组作为一个单元赋给另一个数组,除初始化以外也不允许使用花括号列表的形式赋值。
下面的代码段演示了一些错误的赋值形式:
/* 一些无效的数组赋值 */ 
#include <stdio.h>
#define SIZE 5 
int main(void) 
{
  int oxen[SIZE] = {5,3,2,8}; /* 初始化没问题 */
  int yaks[SIZE]; yaks = oxen; /* 不允许 */
  yaks[SIZE] = oxen[SIZE]; /* 数组下标越界 */
  yaks[SIZE] = {5,3,2,8}; /* 不起作用 */ 
···
}

注意数组下标越界:oxen数组的最后一个元素是oxen[SIZE-1],所以oxen[SIZE]和yaks[SIZE] 都超出了两个数组的末尾。

9.指定数组大小: 

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之前不允许
数组元素引用时,应注意以下问题:
  1. 下标表达式的值必须是一个整型的量,可以是整型常量、整型变量或运算结果为整型的表达式。
  2. 只能单个使用数组中的元素,而不能引用整个数组(字符数组除外)。
  3. C语言的数组下标是从0开始的,因此数组的下标范围为0~L-1,其中L为数组的长度。C语言中不对数组进行越界检查。数组a包含了6个元素,若有语句a[10]=2;,编译时不出错,但可能导致其他变量或程序出错。
  4. 数组里所有的元素具有相同的数据类型。
  5. 一旦创建,不能改变大小。
  6. 数组中的元素在内存中是紧密连续排列的。
  7. flizny == &flizny[0]; // 数组名是该数组首元素的地址
    flizny &flizny[0] 都表示数组首元素的内存地址( & 是地址运算符)。

二.二维数组

1.二维数组类型说明的一般格式:类型说明符 数组名[常量表达式1][常量表达式2];其中,常量表达式1用来定义数组的行数,常量表达式2用来定义了二维数组x的列数。

如定义的二维数组x,由3行3列9个元素组成。元素的行、列下标都从0开始。这9个元素分别为

x[0] [0]  x[0] [1]  x[0] [2]

x[1] [0]  ×[1] [1]  x[1] [2]                                                                                                                      x[2] [0]  x[2] [1]  x[2] [2]

2.二维数组的初始化:                                                                                                                           <1.给全部元素赋初值

    (1)按行赋初值。例如:int a[2] [3]={(1,2,3),(4,5,6)};

    (2)按存储结构赋值,所有数据放在一个花括号中。                                                                            例如:int a[2][3]={1,2,3,4,5,6}; /★与按行赋值等效★/

   <2.给部分元素赋初值,未赋值元素的值为0

    (1)按行赋初值。例如:int a[2][3]={(1, 2, 3),(4)};则a[1][1], a[1][2]的值为0。                                  (2)按存储结构赋值,所有数据放在一个花括号中。例如:int al2][3]=(1,2,3,4);                                  同样a[1][1], a[1][2]的值为0。

   <3.省略二维数组的行数,二维数组的列数不能省略                                                                            (1)按行赋初值。例如:int a[ ][3]={(1,2,3),(4)};系统自动定义数组a的行数为2。                      (2)按存储结构眼值,数组的行数为花括号中元素的个数除以教组的列数向上取整。                        例如:int a[ ][3]={1,2,3,4};花括号中包含4个元素,用4/3向上取整,则系统自动定义数组a的行      数为2。

3.二维数组的引用:定义了二维数组以后,可以用下列格式引用二维数组中的每个元素。                 数组名[下标][下标]   例如:

int c[3] [2];

c[1] [1]=2;

c[1] [2]=C[1] [1]*2;

演示一个较为复杂的代码

/* rain.c -- 计算每年的总降水量、年平均降水量和5年中每月的平均降 水量 */ 
#include <stdio.h>
#define MONTHS 12 // 一年的月份数 
#define YEARS 5 // 年数 
int main(void) 
{// 用2010~2014年的降水量数据初始化数组 
  const float rain[YEARS][MONTHS] = {
  { 4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6 },
  { 8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3 }, 
  { 9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4 }, 
  { 7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2 }, 
  { 7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2 }}; 
  int year, month;
  float subtot, total;
  printf(" YEAR RAINFALL (inches)\n");
  for (year = 0, total = 0; year < YEARS; year++) 
  { // 每一年,各月的降水量总和 
   for (month = 0, subtot = 0; month < MONTHS; month++) subtot += rain[year][month]; 
  printf("%5d %15.1f\n", 2010 + year, subtot); 
  total += subtot; // 5年的总降水量 
  }
  printf("\nThe yearly average is %.1f inches.\n\n", total / YEARS);
  printf("MONTHLY AVERAGES:\n\n");
  printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
  printf(" Nov Dec\n");
  for (month = 0; month < MONTHS; month++)
  { // 每个月,5年的总降水量 
   for (year = 0, subtot = 0; year < YEARS; year++) subtot += rain[year][month]; 
  printf("%4.1f ", subtot / YEARS); }printf("\n"); 662
  return 0; 
}
/*下面是该程序的输出: 
YEAR RAINFALL (inches) 
2010 32.4 
2011 37.9 
2012 49.8 
2013 44.0 
2014 32.9 
The yearly average is 39.4 inches. MONTHLY AVERAGES: 
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 
7.3 7.3 4.9 3.0 2.3 0.6 1.2 0.3 0.5 1.7 3.6 6.7 */
程序解释:  该程序使用了两个嵌套for 循环。第 1 个嵌套 for 循环的内层循环,在 year 不变的情况下,遍历month 计算某年的总降水量;而外层循环,改变 year 的值,重复遍历month ,计算 5 年的总降水量。这种嵌套循环结构常用于处理二维数组,一个循环处理数组的第1 个下标,另一个循环处理数组的第 2 个下标:
for (year = 0, total = 0; year < YEARS; year++)
{ // 处理每一年的数据
for (month = 0, subtot = 0; month < MONTHS; month++)
...// 处理每月的数据
...//处理每一年的数据
}

第2个嵌套for循环和第1个的结构相同,但是内层循环遍历year,外层循 环遍历month。记住,每执行一次外层循环,就完整遍历一次内层循环。因此,在改变月份之前,先遍历完年,得到某月 5 年间的平均降水量,以此类推:

for (month = 0; month < MONTHS; month++)
{ // 处理每月的数据
for (year = 0, subtot =0; year < YEARS; year++)
...// 处理每年的数据
...// 处理每月的数据
}

三.多维数组

1.声明一个三维数组:int box[10][20][30]:和二维数组均类似。
注意:处理三维数组要使用3重嵌套循环,处理四维数组要使用4重嵌套 循环。对于其他多维数组,以此类推。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Franic_wy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值