目录
数组
- 一组相同类型元素的集合,可存储一系列相同类型的数据;
- 在内存中,数据时依次挨着存放,彼此之间没有缝隙;
- 数组属于构造类型;
- 数组可分为,一维数组、二维数组等;
一,一维数组
一维数组的声明:
- type name[size]
- 包含:元素类型type,数组名name,元素个数size;
- 元素类型,任意有效类型均可,也可数组类型;
- 元素个数,必须是大于零的整数常量;
- 数组类型为,tpye [size],是一种构造类型;
- 包含:元素类型type,数组名name,元素个数size;
int main()
{
char arr1[10]; //拥有10个字符的arr1数组
int arr2[10]; //拥有10个整型的arr2数组
double arr3[10]; //拥有10个浮点的arr3数组
int* arr4[10]; //拥有10个指针类型的arr4数组
//因为数组类型为type[size],所以可使用sizeof求其字节大小
int sz1 = sizeof(char[10]); //10
int sz2 = sizeof(int[10]); //40
int sz3 = sizeof(double[10]); //80
int sz4 = sizeof(int*[10]); //40
return 0;
}
int main()
{
int n = 10;
int arr[n]; //报错,n必须是整数常量
return 0;
}
//注:在C99标准下是支持n变量的,称为变长数组,即数组的大小是变量;
//VS2019,不支持
一维数组的初始化:
- 在创建数组时,给数组赋予一些合理初始值;
- 使用{}将值括起来,用逗号,分开;
- 元素个数不可超出,相同时为完全初始化,小于时为不完全初始化;
- 可完全初始化,即给每个元素均赋值;
- 也可不完全初始化,即只给部分元素赋值,剩余会用0、\0或0.0替代;
- 初始化时,可不指定数组的元素个数,其元素个数由初始化值确定;
int main()
{
//完全初始化
char arr1[5] = { 'a','b','c','d','e' };
int arr2[5] = { 1,2,3,4,5, };
int* arr3[5] = { arr2,arr2 + 1,arr2 + 2,arr2 + 3,arr2 + 4 };
//不完全初始化
char arr4[5] = { 'a','b' }; //其余为'\0'
int arr5[5] = { 1,2 }; //其余为0
double arr6[5] = { 1.5,2.5 }; //其余为0.0
//可不指定元素个数
int arr7[] = { 1,2,3,4,5, }; //元素个数为5个
return 0;
}
注:
- 如元素值均为0,或不知初始化何值,可直接简写为{0};
- 除0可简写外,其他初始化同样值,均需写全;
int main()
{
//所有元素初始化0
char arr1[5] = { 0 };
int arr2[5] = { 0 };
//所有元素初始1
int arr3[5] = { 1,1,1,1,1 };
return 0;
}
一维数组元素的访问:
- 数组使用 ”下标引用操作符[ ]“ 来访问的;
- 形式为,数组名[元素下标],元素下标从0开始;
- 可利用sizeof,求数组元素个数;
int main()
{
int arr[5] = { 1,2,3,4,5, };
//访问第三个元素
int a = arr[2];
arr[2] = 2;
int sz = sizeof arr / sizeof arr[0]; //或sizeof(arr)/ sizeof(arr[0])
return 0;
}
一维数组内存存储形式:
- 数组数据在内存中,是连续存储的;
- 如上数组arr3,每个元素的大小为4个字节,所以元素间地址应该相隔4个字节;
- 随着数组下标的增长,元素的地址为递增的;
二,二维数组
- 数组的元素也为数组,即数组的数组;
二维数组的声明:
- type name[size][size]
int main()
{
int arr[2][3]; //一个数组有两个元素,其元素是有三个整型元素的数组
}
二维数组的初始化:
- 初始化时,第一个[ ]内数字可省略;
int arr[2][3] = { {1,2,3},{4,5,6} }; //也可直接{1,2,3,4,5,6}
int arr[][3] = { {1,2,3},{4,5,6} };
二维数组元素的访问:
- 形式为,数组名[下标][下标],元素下标从0开始;
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int a = arr[1][2];
arr[1][2] = 7;
int sz = sizeof(arr)/sizeof(arr[0][0]); //等同于sizeof(int[2][3])/sizeof(arr[0][0])
return 0;
}
二维数组内存存储形式:
- 也是随着下标从低地址向高地址依次连续存储;
三,数组传参
数组作为函数的参数
- 实际上是,将首元素的地址传递给参数;
两种形式:
- 数组形式,如形参为int arr[ ],或int arr[ ][2];
- [ ]内数字可省略(因为是地址所以无关);
- [ ][2]只有前一个[ ]内数字可省略;
- 指针形式,如形参为int* p;
- int arr[3][2]指针形式为int (*arr)[2];
//形参为数组形式
//[]内写不写,写多少均不影响
void PrintArr1(int arr[], int sz)
{
int i = 0;
for (i; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
//形参为指针形式
void PrintArr2(int* p, int sz)
{
int i = 0;
for (i; i < sz; i++)
{
printf("%d ", *(p + i));
}
}
int main()
{
int arr[5] = { 1,2,3,4,5, };
int sz = sizeof arr / sizeof arr[0];
PrintArr1(arr, sz);
PrintArr2(arr, sz);
return 0;
}
//结果:1 2 3 4 5 1 2 3 4 5
注:
- 数组传参实际传的是地址,所以sizeof求大小时,实际求的是地址的大小;
- 此情况下,需在函数外计算好大小,在作为参数传递给函数;
void PrintArr(int arr[])
{
int sz = sizeof arr / sizeof arr[0];
printf("%d ", sz);
}
int main()
{
int arr[5] = { 1,2,3,4,5, };
PrintArr(arr);
return 0;
}
//结果:1
数组名含义:
- 数组名为数组首元素的地址,即&arr[0];
- 例外,sizeof arr 和 &arr ,此两数组名表示整个数组;
int main()
{
char arr[5] = { 'a','b','c','d','e' };
printf("%d ", sizeof(arr)); //5
printf("%p %p ", &arr, &arr + 1); //00D5FC58 00D5FC5D 相差5
printf("%p %p ", arr, arr + 1); //00D5FC58 00D5FC59 相差1
return 0;
}
四,案例
1,冒泡排序;
//冒泡排序(依次比较排序),只针对整数int类型
void bubbleSort(int arr[], int sz)
{
//第一次循环,从首个元素依次比较交换位置,循环9次,(如是最大数则会排到最后一位)
//第二次循环,再从首个元素依次比较交换位置,循环8次(最后一位无需比较了),(如是最大数则会排到倒数第二位)
//依次循环,总共循环9次
for (int i = 0; i < sz - 1; i++)
{
int flag = 1;
for (int j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;
}
}
if(flag)
break;
}
}
//递归方式
void bubbleSort(int* arr, int sz)
{
int flag = 1;
for (int i = 0; i < sz - 1; i++)
{
if (arr[i] > arr[i + 1])
{
int tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
flag = 0;
}
}
if (sz > 1 && flag == 0)
bubbleSort(arr, sz - 1);
}
2,三子棋(完整的VisualStudio文件需下载在VisualStudio打开);