一、数组
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个标识符命名,并通过编号(索引,亦称为下标或角标)的方式对这些数据进行统一管理。
1、名词解释
- 数组名:本质上是一个标识符常量,命名需要符合标识符规范。
- 元素:同一个数组中的元素必须是相同的数据类型。
- 下标(索引、角标):从0开始的连续数字。
- 数组的长度:表示元素的个数。
2、数组特点
- 创建数组时会在内存中开辟一整块连续的空间,占据的空间的大小,取决于数组的长度和数组中元素的类型。
- 数组中的元素在内存中是依次紧密排列的且有序的。
- 数组一旦初始化完成,其长度就是确定的,数组的长度一旦确定,就不能修改。
- 我们可以直接通过索引(下标)获取指定位置的元素,速度很快。
3、数组的定义
1、先指定元素的个数和类型,再进行初始化
// 定义一个数组,数组名字是arr1,元素类型是int,元素个数是3个
int arr1[3];
// 定义完后为每个元素赋值
arr1[0] = 10;
arr1[1] = 20;
arr1[2] = 30;
2、指定数组类型和个数直接进行初始化
// 定义一个int类型的数组,数组名是arr2,元素个数是3,并且进行初始化
int arr2[3] = {100, 200, 300};
3、指定数组类型直接进行初始化,没有设定个数
// 没有指定元素个数,系统会自动计算
int arr3[] = {1, 2, 3, 4, 5};
(c99允许数组的长度可变,数组长度确定前可变,确定长度后不可变)
4、c99允许直接使用数组直接量存储数据
100; // 字面量-直接量
12.345f; // 字面量-直接量
(int[3]){10, 20, 30}; // 数组直接量
for (int i = 0; i < 3; i++)
{
printf("%d \n", (int[3]){10, 20, 30}[i]);
}
4、访问数组元素
1、通过数组名(下标)访问数组中的元素。
#include <stdio.h>
int main()
{
// 定义一个int类型的数组,有3个数元素,并且进行初始化
int arr1[3] = {10, 20, 30};
// 通过索引(下标)修改第二个位置的数据
arr1[1] += 100;
printf("第一个元素值为:%d \n", arr1[0]);
printf("第二个元素值为:%d \n", arr1[1]);
printf("第三个元素值为:%d \n", arr1[2]);
return 0;
}
2、数组越界
数组下标必须在指定范围内使用,超出范围视为越界。
3、计算数组长度
数组长度(元素个数)是在数组定义时明确指定且固定的,我们不能在运行时直接获取数组长度,但是,我们可以通过sizeof 运算符间接计算出数组长度,计算步骤如下:
- 使用sizeof运算符计算出整个数组的字节长度。
- 由于数组成员是同一类型,每个元素字节长度相等,用整个数组的字节长度除以单个元素的字节长度就可以得到数组的长度。
#include <stdio.h>
int main()
{
// 计算数组的长度,默认数组的长度已经固定,运行的时候无法获取,可以使用sizeof来进行计算
int arr[] = {10, 20, 30, 40, 50};
// 数组元素的类型是固定的,那么可以直接获取arr的总字节长度
int arr_byte_length = sizeof arr;
// 先计算出数组中某个元素的字节数,再根据总的字节长度,除以某个元素的字节长度,即可获取元素个数
int element_byte_length = sizeof arr[0];
// 元素的个数
int arr_length = arr_byte_length / element_byte_length;
// 输出数组的长度
printf("数组的元素个数为:%d \n", arr_length);
// 上面代码可以简化
int arr_length1 = (sizeof arr) / (sizeof arr[0]);
printf("简化代码后的数组元素个数结果:%d \n", arr_length1);
return 0;
}
4、数组遍历
遍历数组是指按顺序访问数组中的每个元素,以便读取或修改它们,编程中一般使用循环结构对数组进行遍历。
#include <stdio.h>
int main()
{
// 遍历数组
int arr[5] = {100, 200, 300, 400, 500};
// 先计算数组的元素个数
int arr_len = (sizeof arr) / (sizeof arr[0]);
for (int i = 0; i < arr_len; i++)
{
printf("数组下标为:%d,元素值为:%d \n", i, arr[i]);
}
return 0;
}
4、数组的应用
例子:求数组和以及平均值
#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 51}, sum = 0;
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++)
{
sum += arr[i];
}
printf("和为%d", sum);
printf("平均值为%.2lf", sum * 1.0 / len);
return 0;
}
和为151平均值为30.20
例子:求最大值和平均值
#include <stdio.h>
int main()
{
int arr[] = {10, 20, 50, 1, 60, 70, 80};
int max_sum = arr[0], min_sum = arr[0];
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++)
{
if (max_sum < arr[i])
max_sum = arr[i];
if (min_sum > arr[i])
min_sum = arr[i];
}
printf("最大值%d", max_sum);
printf("最小值%d", min_sum);
return 0;
}
最大值80最小值1
4、字符数组
1、方式一:最后一个元素设置成 \0
在给某个字符数组赋值时,赋值的元素个数小于字符数组的长度,则会自动在后面加 '\0', 表示字符串结束; 赋值的元素的个数等于该数组的长度(或不指定数组长度),则不会自动添加 '\0'。
#include <stdio.h>
int main()
{
// 定义字符数组(也可以叫字符串) \0----结束标识
// 定义char类型的数组,设置5个元素数,并显示设置\0
char chs1[5] = {'a','b','c','d','\0'};
// 指定长度,没有显示设置\0,默认会自动加上
char chs2[4] = {'t','o','m'};
// 没有指定数组元素个数,也没有显示指定\0
char chs3[] = {'j', 'a', 'c', 'k'};
// 输出这些字符串
printf("%s \n",chs1);
printf("%s \n",chs2);
// 由于没有显示设置结束标识,那么默认会把相邻内存中的数据读取出来,直到找到\0结束标识位置
printf("%s \n",chs3);
// 总结:字符数组指定了元素个数后,需要在结尾指定结束标识\0,
// 如果字符数组指定了元素个数,元素数据中没有指定结尾标识,系统会自动加上结束标识\0
// 如果字符数组指定了元素个数,但是元素个数和指定长度相同,那么结尾处也没有结束标识\0
// 系统没有自动添加结束标识\0,也没有显示指定,输出的时候会把相邻的内存中的字符全部读取出来,直到遇到结束标识为止
return 0;
运行结果
abcd
tom
jacktom
方法二、简化写法
#include <stdio.h>
int main()
{
// 简化字符数组写法
// 默认会自动添加结束标识\0
char chs1[] = {"what are you no sha lei"};
printf("%s \n", chs1);
// 省略大括号,默认也会自动加\0
char chs2[] = "no sha lei ni shuo ne";
printf("%s \n", chs2);
return 0;
}
5、二维数组
如果数组的元素还是数组,这样的数组就称为多维数组。这种多层次的结构允许我们以表格或矩阵的方式组织数据,其中每个维度都对应于不同的行、列或更多的维度,使数据更加结构化和有组织。
多维数组可以分为二维数组、三维数组、四维数组 …… 等,这里我们以二维数组为例进行演示。
1、二维数组写法
方法一、
#include <stdio.h>
int main()
{
int arr[2][3]; // 定义一个2行3列的二维数组
// 为数组元素赋值
arr[0][0] = 10;
arr[0][1] = 20;
arr[0][2] = 30;
arr[1][0] = 40;
arr[1][1] = 50;
arr[1][2] = 60;
return 0;
}
方法二、
#include <stdio.h>
int main()
{
// 直接定义并以矩阵的方式初始化二维数组
int arr1[3][4] = {
{10, 20, 30, 40},
{50, 60, 70, 80},
{90, 100, 110, 120}};
// 定义三行四列的二维数组(自动匹配隔行割裂)
int arr2[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// 定义三行三列的二维数组,只设置列,也会自动匹配(一维可以不进行预设)
int arr3[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
return 0;
}
2、二维数组的遍历
访问二维数组的元素,需要使用两个下标(索引),一个用于访问行(第一维),另一个用于访问列(第二维),我们通常称为行下标(行索引)或列下标(列索引)。
遍历二维数组,需要使用双层循环结构。
例子1、
#include <stdio.h>
int main()
{
int arr[3][4] = {
{10, 20, 30, 40},
{50, 60, 70, 80},
{90, 100, 110, 120}};
int rows=sizeof(arr)/sizeof(arr[0]),cows=sizeof(arr[0])/sizeof(int);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cows; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
return 0;
}
例子2、
// 现在有三个班,每个班五名同学,用二维数组保存他们的成绩,并求出每个班级平均分、以及所有班级平均分,数据要求从控制台输入。
#include <stdio.h>
int main()
{
int scores[3][5];
double sum_scores = 0, all_sum_scores = 0;
int rows = sizeof(scores) / sizeof(scores[0]);
int cows = sizeof(scores[0]) / sizeof(scores[0][0]);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cows; j++)
{
printf("请输入第%d个班级的第%d个同学的分数:\n", i + 1, j + 1);
scanf("%d", &scores[i][j]);
}
printf("\n====================================================\n");
}
for (int i = 0; i < rows; i++)
{
sum_scores = 0;
printf("第%d个班级每个人分数分别为:",i+1);
for (int j = 0; j < cows; j++)
{
sum_scores += scores[i][j];
printf("%d ",scores[i][j]);
}
printf("\n第%d个班的总分为%.2lf,平均分为%.2lf\n", i + 1, sum_scores, sum_scores / cows);
all_sum_scores += sum_scores;
}
printf("所有班级的平均分为:%.2lf", all_sum_scores / rows);
return 0;
}
运行案例
请输入第1个班级的第1个同学的分数:
10
请输入第1个班级的第2个同学的分数:
10
请输入第1个班级的第3个同学的分数:
10
请输入第1个班级的第4个同学的分数:
10
请输入第1个班级的第5个同学的分数:
11
====================================================
请输入第2个班级的第1个同学的分数:
10
请输入第2个班级的第2个同学的分数:
10
请输入第2个班级的第3个同学的分数:
10
请输入第2个班级的第4个同学的分数:
10
请输入第2个班级的第5个同学的分数:
12
====================================================
请输入第3个班级的第1个同学的分数:
10
请输入第3个班级的第2个同学的分数:
10
请输入第3个班级的第3个同学的分数:
10
请输入第3个班级的第4个同学的分数:
10
请输入第3个班级的第5个同学的分数:
13
====================================================
第1个班级每个人分数分别为:10 10 10 10 11
第1个班的总分为51.00,平均分为10.20
第2个班级每个人分数分别为:10 10 10 10 12
第2个班的总分为52.00,平均分为10.40
第3个班级每个人分数分别为:10 10 10 10 13
第3个班的总分为53.00,平均分为10.60
所有班级的平均分为:52.00