数组的概念
什么是数组
数组是相同类型,有序数据的集合。
数组的特征
-
数组中的数据被称为数组的元素,是同构的
-
数组中的元素存放在内存空间里(char player_name[6]:申请在内存中开辟6块连续的基于char类型的变量空间)
衍生概念:下标(索引)
-
下标或索引代表了数组中元素距离第一个元素的偏移位置。
-
数组中元素的地址值,下标越大,地址值越大。(每一块内存空间都有一个独有的内存地址)
-
数组的下标都是从0开始的。
一维数组
数组的定义
类型说明符 数组名[数组容量]
说明:
-
数组的类型说明符有数组中的元素来决定,也就是元素是什么类型,数组就是什么类型
-
数组名也是标识符,我们所说的数组(名),大家可以理解为数据类型是数组的变量(名)
-
数组容量也可以叫做常量表达式,举例:
int ages[10]、int lcd[1024*768]
类型:代表了数组中元素的类型
容量:数组中能存储多少个元素,数组容量可以是一个常常量、常量表达式,还可以是符号常量,但必须整型。
深入理解:
-
定义一个数组,相当于申请了一个可以容纳所指定元素数量的内存单元。所申请的内存单元是连续的
-
定义一个数组,相当于定义了多个匿名变量,这些变量也可以通过
数组名[下标]
来标识。
举例:
//定义一个数组 int arr[10]; //问题:上面数组中,最小下标0.最大下标9
经过上面的案例,分析得到
数组的最大下标=数组元素个数(数组容量)-1
数组元素的访问
原则:数组中的元素不能一次性访问所有的元素,只能一个一个的访问。
访问方式:
数组名[下标]
举例:
//定义一个容纳10个元素的int数组 int arr[10]; //给数组的第一个元素进行赋值 arr[0]= 89;//访问数组的第一个元素 int a = arr[0]; // 问题:以下访问是否正确 int b= arr[10];// error,下标越界异常
注意:数组元素的访问一定不能越界。
/***
*需求:一维数组案例-引用数组元素。利用循环给数组元素a[0]~a[9]赋值0~9,并且逆序输出
*/
#include <stdio.h>
int main()
{
//创建一个一维数组
int arr[10];
//使用for循环给数组赋值
for(int i = 0;i < 10;i++)
{
arr[i] = i;
}
//逆序输出,我们通过循环将数组中的元素一个个取出来,称之为遍历
for(int j = 9;j >= 0;j--)
{
printf("%d ",arr[j]);
}
printf("\n");//纯粹换行
return 0;
}
/*********************************
9 8 7 6 5 4 3 2 1 0
*********************************/
数组的初始化
定义数组的同时,用指定数据来给对应元素赋值。
简化数组定义后,需要对元素一一赋值操作。
语法规则:
类型 数组名[容量] = {常量1,常量2,常量3...};
注意事项:
数组可以部分初始化:也就是可以给数组中前几个元素初始化,未被初始化的元素系统将自动初始化,比如0;如果定义数组时未指定数据容量,则系统会根据初始化元素的个数来决定数组容量。
//1.如果定义数组时只给数组前几个初始化,后续剩余元素会自动完成初始化,比如赋值0 int arr[10] = {1,2,3,4,5} //等价于以下写法 int arr[10] = {1,2,3,4,5,0,0,0,0,0} //2.如果定义数组时未指定数据容量,根据初始化元素个数来决定容量 int arr[] = {1,2,3,4,5}//推荐写法,等价于以下写法 int arr[5] = {1,2,3,4,5}
衍生概念:
-
柔性数组:柔性数组的概念是在C99标准,针对结构体的最后一个成员可以是一个未被指定大小的数组;
广义简单理解:数组容量待确定的数组,举例:int arr[] = {1,2,3,4,5}
面试题:
-
在不知道数组类型的情况下,如何确定数组元素的个数
int length = sizeof(arr) / sizeof(arr[0])
说明:
1.arr就是我们计算的数组本身, sizeof(arr)
用来计算该数组中总的字节大小。
2.sizeof(arr[0])
用来计算数组中一个元素所占的字节大小,因为数组中的元素类型相同,所以计算哪一个都行。
3.sizeof(arr)/sizeof(arr[0])
就是用数组中总的字节数除以每一个元素所占的字节数,从而得到元素的个数。
数组中的元素里的默认值
在C语言中,当你声明一个数组时,如果没有为数组的元素赋初值,那么数组的元素将会采用默认值。默认值取决于数组的类型。 整数类型的数组(int)
:默认值通常是0。这意味着,如果你声明一个整数类型的数组而没有显式地为其元素赋值,那么数组中的每个元素都会被初始化为0。
浮点数类型的数组(float/double)
,默认值通常是0.0。
字符类型的数组(char)
,默认值通常是nul字符('')。这意味着,如果你声明一个字符类型的数组而没有显式地为其元素赋值,那么数组中的每个元素都会被初始化为null字符。
需要注意的是,这些默认值只在声明数组时生效,如果你在后续的代码中为数组的元素赋了其他值,那么默认值将被覆盖。
一维数组案例
案例1:
/***
*需求:一维数组案例-非波拉契数列
*/
#include <stdio.h>
int main()
{
int i;//循环变量
int f[20] = {1,1};//定义一个数组,用来存储数列,默认存储第一位和第二位
int length = sizeof(f)/sizeof(f[0]);//计算数组的元素个数
//生出数列存入数组
for(i = 2;i < length;i++)
{
//给数组元素赋值,从数组的第三个元素开始
f[i] = f[i - 2] + f[i - 1];
}
//遍历数组
//通过循环将数组中的每一个元素取出来,称之为遍历
for(i = 0;i < length;i++)
{
//遍历的时候,要求一行显示5个数
if(i % 5 == 0)
{
printf("\n");
}
printf("%6d",f[i]);
}
printf("\n");
return 0;
}
数组的典型应用:数据排序
冒泡排序
-
向后冒泡
思想:
1.一次只排好一个数,针对n个数,最差情况需要n-1次就可以排好
2.每次排序将相邻数据两两比较,将较大或较小的数据向后交换,等所有数据都比较完成,将较大/较小的数就会出现在最后,这也是该数应该有的位置。
3.在余下的数中,再次应用第2步的操作,直到只剩下一个数。
-
向前冒泡
思想:
1.一次只排好一个数,针对n个数,最差情况需要n-1次就可以排好
2.每次排序假定第一个元素是最大/最小的,用第一个元素的后面的元素一一与第一个元素比较,遇到较大/较小的和第一个元素交换,访问完数组的最后一个元素,就排好了一个数;
3.在余下的数中,再次应用第2步的操作,直到只剩下一个数。
一维数组案例
案例2:
/*
需求:一维数组案例-冒泡排序
*/
#include <stdio.h>
int main()
{
//创建一个数组,用来存储排序的数列
int arr[11];
int i,j,t;//i:比较的轮数,j:每一轮比较的次数;t:临时变量,用来比较时存放数据
printf("请输入11个测试整数:\n");
//计算数组的大小
int length = sizeof(arr) / sizeof(int);//这里sizeof(int)等价于sizeof(arr[0]);
for(i = 0;i < length;i++)
{
scanf("%d",&arr[i]);
}
printf("\n");
//对数组arr使用冒泡进行排序(注意:我们使用标准冒泡,大家也可以自行补充优化版的冒泡,如鸡尾酒排序法等等)
//外层循环:控制比较的轮数,因为有11个数,所以我们完那需要比较length -1轮,也就是比较10轮
for(i = 0;i <length -1;i++)
{
//内层循环:每一轮比较的次数,每一轮比较的次数为length -1 -i
for(j = 0;j <length -1;j++)
{
//相邻的两个数进行比较,满足条件交换位置
if(arr[j]>arr[j+1])
{
t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
}
printf("冒泡排序改后遍历数组:\n");
for(i = 0;i < length;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
/*******************************************
请输入11个测试整数:
12 33 8 4 10 27 2 7 9 17 6
冒泡排序改后遍历数组:
2 4 6 7 8 9 10 12 17 27 33
*******************************************/
案例3:
/*
需求:从键盘输入年、月、日,计算并输出该日是该年的第几天。
*/
#include <stdio.h>
int main()
{
//定义变量:年,月,日,统计总的天数,循环变量,用来遍历当前月份前的月份
int y,m,d,sum,k;
//定义一个数组,用来存放1~12月每月的天数
int t[] = {31,0,31,30,31,30,31,31,30,31,30,31};//柔性数组
printf("请输入年份、月份、天:\n");
scanf("%d年%d月%d日",&y,&m,&d);
//因为二月比较特殊,存在平年和润年这样的因素,所以需要进行平年和润年的判断
if((y % 4 == 0 && y %100 != 0)||y %400 ==0)
{
t[1] = 29;//润年2月29
}
else
{
t[1] = 28;//润年2月28
}
sum = d;//最后一月的天数
//这是概念的第几天
for(k = 0;k < m-1;k++)
{
sum += t[k];//叠加前几个月的天数
}
printf("%d月%d日是%d年的第%d天\n",m,d,y,sum);
return 0;
}
/*********************************************
请输入年份、月份、天:
2024年8月1日
8月1日是2024年的第214天
**********************************************/
以上就是C语言一维数组学习笔记,有什么问题还请指正,谢谢!