概念:
数组,是指多个相同类型的数据,按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
数组中的概念:
数组名
下标(索引)【下标从零开始】
元素
数组的长度
数组的特点:
1.数组中的元素在内存中是依次紧密排列的,有序的。
2.创建数组对象会在内存中开辟一整块连续的空间,占据的空间的大小,取决于数组的长度和数组中元素的类型。
3.我们可以直接通过下标的方式调用指定位置的元素。
4.数组,一旦初始化完成,其长度就是确定的。数组的长度一旦确定,就不能再修改。
5.数组名中,引用的是这块连续空间的首地址。
数组的分类:
一维数组:存储一组数据
二维数组:存储多组数据,相当于二维表,一行代表一组数据,每一行长度可以不同
高维数组…………

按数据类型分类:
int类型数组
char类型数组
double类型数组
……………………
一维数组的定义方式:
int arr [10];(数组arr,里面包含10个元素,每个元素都是int类型)
或者:
#define NUM 10
int arr 【NUM】;
数组元素的调用:
格式:
数组名[下标](数组名的下标从0开始)
数组角标越界:

关于长度:
数组的字节长度:
sizeof运算符会返回整个数组的字节长度。
比如:
#include<stdio.h>
int main() {
int arr [10];
printf("%zd",sizeof(arr));
return 0;
}
输出为40
数组的长度:
#include<stdio.h>
int main() {
int arr[20];
printf("数组的长度为%zd\n",sizeof(arr)/sizeof(int));
return 0;
}
输出为:数组的长度为20(注意中括号中的数字)
一维数组的遍历:
举例:
//声明长度为10的int类型的数组,给数组中的元素依次赋值0到9,并遍历数组中的所有元素
#include<stdio.h>
int main() {
int arr[10];
size_t length = sizeof(arr)/sizeof(int);
for (int i =1;i <length;i++) {
arr[i] = i;
printf("arr[%d] = %d;\n",i,i);
}
printf("遍历一维数组的数据:\n");
for (int i =0;i < length;i++) {
printf("%d",arr[i]);
}
return 0;
}
数组的其他定义方式:
定义方式2:
数组可以在声明时,使用大括号,同时对每一个元素赋值。比如:
int arr[5] = {22,37,90,48,95};
变形1:
int arr[ ] = {22,37,90,48,95};
(即省略中括号中的数字)
变形2:
对数组部分元素赋初值,如果大括号里面的值,少于数组的元素数量,那么未赋值的元素自动初始化为0
比如:
int arr[5] = {10,20,30,0,0};
变形3:
将每一个元素都赋值0,比如:
int a[100] = {0};
变形4:
给特定位置的元素赋值:
int arr[10] = {[1]=5,[9]=35}(给第二位数字和最后一位数字赋值,未指定的索引位置自动赋0)
错误方式:
int arr[3] = {1,2,3,4}
使用大括号时,大括号里的值不能多于数组的长度,否则编译时会报错
一维数组的内存分析:

注意事项:
C语言规定,数组变量一旦声明,数组名指向的地址就不可更改。这是因为声明数组时,编译器会自动为数组分配内存地址,这个地址与数组名时绑定的,不可更改的。
当数组定义之后,再用大括号重新赋值是不允许的,会报错。
比如:

变长数组:
数组声明的时候,数组长度除了使用常量,也可以使用变量或者表达式来指定数组的大小,这叫做变长数组。
方式一:
例如:
int n = 10;
int arr[n];
这种方式只有在运行时才确定数组长度。
任何长度需要运行时才能确定的数组,都叫变长数组,例如:
int i = 10;
int ai[i];
int a2[i +5];
int a3[i +k];
注意:变长数组在c99标准中被引入,某些编译器可能不支持变长数组,或者有特定的限制
//在c99标准中,支持变长数组,例如:
int length = 10;
int arr[length];
int arr2[length + 5];
方式二:
使用malloc()函数来创建动态大小的数组
看不懂,等学了指针再看看
一维数组的练习:
数值型数组特征值统计:
举例1:
//声明长度为10的int类型的数组,包含十个元素,然后求出数组的最大值,最小值,总和,平均值,并输出
#include "stdio.h"
int main() {
int i,max, min,total = 0;
double average;
int arr[10] = {132,12313,4124,31231,123123,12314,4123432,24523523,134231,254235};
min = arr[0];
max = arr[0];
for (i = 0; i < sizeof(arr)/sizeof(int);i++) {
if(arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}total +=arr[i];
}
average = total/10.0;
printf("最大数是%d\n",max);
printf("最小数是%d\n",min);
printf("总和是%d\n",total);
printf("平均数是%.2lf\n",average);
return 0;
}
举例2:评委打分
#include<stdio.h>
int main() {
int min,max,i,total =0;
double average;
int arr[] = {5,4,6,8,9,0,1,2,7,3};
max = arr[0];
min = arr[0];
for (i = 0;i < sizeof(arr) / sizeof(int);i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
total += arr[i];
}
average =(total - max - min + 0.0)/(sizeof(arr) / sizeof(int)-2);
printf("平均数是%.2lf\n",average);
return 0;
}
数组的复制:
由于数组名是指针,所以复制数组名不能简单得复制数组名
错误示范:
int a[3]={10,20,30}
int *b;
b = a;
上述写法结果不是将数组a赋值给数组b,而是让a和b指向同一个数组。
正确写法1,使用循环:
复制数组最简单的方法,将数组元素逐个进行复制,比如将数组a的成员逐个复制给数组b
举例:
//测试一维数组的复制
#include<stdio.h>
#define LENGTH 3
int main() {
int arr1[LENGTH] ={10,20,30};
int arr2[LENGTH];
int i;
for (i = 0; i < LENGTH; i++) { //使用循环遍历arr1,同时给arr2中的元素赋值
arr2[i] = arr1[i];
printf("%d ",arr2[i]);
}
return 0;
}
正确方式2,使用memcpy()函数:
memcpy()函数定义在头文件string.h中,直接把数组所在的那一段内存,再复制一遍。
3个参数依次为:目标函数,源数组,要复制的字节数
举例:(注意第三个参数是要复制的字节数,要乘sizeof(int))
//测试一维数组的复制
//memcpy函数3个参数依次为:目标函数,源数组,要复制的字节数
#include<stdio.h>
#include<string.h>
int main() {
int arr1[3] = {10,20,30};
int arr2[3];
//使用memcpy函数复制数组1到数组2
memcpy(arr2,arr1,3 * sizeof(int));
//打印数组2的内存
printf("复制后的数组2:");
for (int i = 0;i < 3;i++) {
printf("%d ",arr2[i]);
}
return 0;
}
两种方式对比:
循环复制:
优点:简单直观,不需要引入头文件
缺点:需要遍历然后逐个赋值,不适合大型数组或复杂数据结构
memcpy函数复制:
优点:快速高效,适用于大型数组和复杂数据结构的复刻,不需要遍历
缺点:要引入头文件,对应简单的数组复制,可能过于繁琐
数组元素的反转:
数组对称位置的元素互换
反转方式1
举例:
//一维数组的反转,就是arr[i]和arr[arr.length-1-i]这两个位置互换
#include<stdio.h>
int main() {
//定义一个数组
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int i;
//获取数组的长度
size_t length = sizeof(arr) / sizeof(int);
//arr[i] 和 arr[arr.length-i-1]这两个位置的元素互换
//反转位置
for (i = 0;i < length / 2;i++) {
//不管奇数还是偶数,判断的范围都是length / 2
int temp = arr[i];
arr[i] = arr[length - i -1];
arr[length - i - 1] = temp;
}
//遍历反转后的数组
for (i = 0;i < length;i++) {
printf("%d ",arr[i]);
}
return 0;
}
char型数组与字符串(难点):
数组元素的数据结构类型为char型的数组
一方面,可以看作普通数组,和上述一致,如:
char arr[]={'a','b','c','d'};
另一方面,字符型数组可以用来存储字符串。
字符串的使用:
由双引号括起来的一串字符称为字符串。
“”被称为空串,什么也没有;“ ”被称为空格串,是包含一个空格字符的字符串。两者不相等。
C语言没有专门用于存储字符串的变量类型,字符串都被存储在char类型的数组中。在字符串结尾,C语言会自动添加一个‘\0’的转义字符作为字符串结束的标志,所以字符数组也必须以‘\0’字符结尾
声明方式1(标准写法):
显示以‘\0'为最后一个字符元素结尾
char str[] = {'h','e','u','i','k','\0'};
如果一个字符数组的声明如下:
char str[10];
那么,由于必须留一个位置给\0,所以这个数组最多只能容纳9个字符的字符串
声明方式2(简化写法):
C语言中,双引号之中的字符,会被自动视为字符数组。
举例
//自动在末尾添加‘\0'字符。
char str1[12] = {"Hello World"};//注意使用双引号,不是单引号
//或者
char atr2[12] = "hello world";//可以省略一对{}来初始化数组元素
方式3(进一步简化):
char str3[] = {"Hello World"};
省略括号中的数字
字符串对应数组的长度:

上述数组的长度不是11,而是12.
字符串的长度:

字符串的长度不包括最后的\0,,所以上述的字符串长度为5.
数组nation前5个元素为C,h,i,n,a,第六个元素是\0,后四个元素也是\0
区分‘\0’,0,‘0’:
字符'\0'不同于字符'0',前者的ASCII码的是0,后者的ASCII码是48
练习1:
比较"x"和'x'
书写形式不同:字符串常量用的是双引号,字符常量用的是单引号
存储空间不同:字符串常量存储时自动加一个结束标志\0,“x”占用2个字节;字符常量只占用一个字节的存储空间,‘x'只占用1个字节
操作也不同:可以对字符常量进行加减运算,字符串常量则不能(假设存储手机号时,就可以存储到字符串中)

多维数组:
二维数组:
对于二维数组的理解,可以看做是由一维数组嵌套而成的,即一维数组array1又作为另一个一维数组array2的元素而存在。
定义方式:
int a[3][4];(可以理解为二维数组由三个一维数组构成,他们的数组名分别为a[0],a[1],a[2]。这三个一维数组各有4个元素。二维数组a共有3*4=12个元素)
如图:

二维数组,常称为矩阵,把二维数组写成行和列的排列形式,可以形象化地理解二维的数组的逻辑结构
三维数组:
int a[3][4][5];(是几维数组就带几个括号)
错误的声明方式
float a[3,4];
(一个中括号内不能写两个下标)
二维数组的内存分析:
在内存中,各元素是连续存放的,不是二维的,是线性的。
C语言中,二维数组中元素排列的顺序是按行存放的
举例:

关于长度:
printf("%zu\n",sizeof(a));//获取二维数组所占用的字节数,输出为48
printf("%d",sizeof(a)/ sizeof(int));//获取二维数组元素个数,输出为12
成员的调用:
格式:
数组名[下标][下标]
和一维数组一样,多维数组的第一个元素也是从0开始的
举例1:
给指定位置的元素赋值

举例2:
查看元素地址:
#include<stdio.h>
int main() {
int i,j;
int arr[3][4];
for(i=0;i<3;i++) {
for(j=0;j<4;j++) {
printf("%p\n",&arr[i][j]);
}
}
return 0;
}
其他的定义方式:
定义方式2:
声明与初始化同时进行
举例:
#include<stdio.h>
int main() {
int arr[3][4] = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
return 0;
}

定义方式3:
多维数组也可以仅为指定的位置进行初始化赋值,其余未赋值的成员会自动设置为零
举例:

定义方式4:
多维数组也可以使用单层大括号赋值,不管数组有多少维度,在内存里都是线性存储,对于a[2][2]来说,a[0][0]后面是a[0][1],再后面是a[1][0],以此类推

定义方式5(在4的基础上简化):
如果对全部元素赋值,那么第一行的长度可以不给出

错误的定义方式:
行可以省略,列不能省略
举例:

1046

被折叠的 条评论
为什么被折叠?



