一维数组
创建
元素类型 | 数组名 | 常量表达式 |
---|---|---|
type_t | arr_name | [const_n]; |
int | arr1 | [10] |
int arr1[10];
int count = 10;
int arr2[count];
char arr3[10];
float arr4[1];
double arr5[20];
注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。
在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,
但是变长数组不能初始化。
初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
看代码:
int arr1[10] = {1,2,3}; //不完全初始化,剩余的元素默认0
int arr2[] = {1,2,3,4}; //省略了数组大小,数组必须初始化,大小根据初始化内容确定
int arr3[5] = {1,2,3,4,5}; //完全初始化
char arr4[3] = {'a',98, 'c'}; //a b c:98 为b的ASCII码值
char arr5[] = {'a','b','c'}; //a b c
char arr6[] = "abcdef"; //a b c \0:字符串最后是\0
数组在创建的时候如果想不指定数组的确定的大小就得初始化。
数组的元素个数根据初始化的内容来确定。
但是对于下面的代码要区分,内存中如何分配
char arr[10] = {1,2,3,4,5,6,7,8,9,10};
// 0,1,2,3,4,5,6,7,8,9
arr[9] == 10;//下标引用操作符
使用
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)//for use ;
{
scanf("%d", &arr[i]);
}
for (i = 0; i < sz; i++)//数组下标从0开始
{
printf("%d ", arr[i]);
}
return 0;
}
int main()
{
int arr[10] = { 0 };
printf("%d\n", sizeof (arr));//40=10*4字节
printf("%d\n", sizeof (arr[0]));//4字节
return 0;
}
存储
数组在内存中的存储
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d] = %p\n", i, &arr[i]);//%p用来打印地址
}
return 0;
}
一维数组在内存中是连续存放的
字节 | 地址 |
---|---|
0低地址 | 00D8F724 |
1 | 00D8F728 |
2 | 00D8F72C |
3 | 00D8F730 |
4 | 00D8F734 |
5 | 00D8F738 |
6 | 00D8F73C |
7 | 00D8F740 |
8 | 00D8F744 |
9高地址 | 00D8F748 |
二维数组
创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
初始化
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
二维数组如果有初始化,行可以省略,列不能省略
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
名称 | 值 | 类型 | |
---|---|---|---|
arr | 0x007cf9a4 {0x007cf9a4 {1, 2, 3, 4}, 0x007cf9b4 {5, 6, 7, 8}, 0x007cf9c4 {9, 10, 11, 12}} | int[3][4] | |
[0] | 0x007cf9a4 {1, 2, 3, 4} | int[4] | |
[1] | 0x007cf9b4 {5, 6, 7, 8} | int[4] | |
[2] | 0x007cf9c4 {9, 10, 11, 12} | int[4] |
使用
定位:arr[2][3]:3行4列,下标从0开始
int main()
{
int arr[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{5,6,7,8,9} };
printf("%d", arr[2][3]);//6
return 0;
}
遍历
int main()
{
int arr[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{5,6,7,8,9} };
int i = 0;
for (i = 0; i < 4; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
存储
int main()
{
int arr[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{5,6,7,8,9} };
int i = 0;
for (i = 0; i < 4; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("&arr[%d][%d] == %p\n", i, j, &arr[i][j]);
}
printf("\n");
}
return 0;
}
二维数组在在内存中也是连续存放的:所以可以省略行,不能省略列。
&arr[0][0] == 004FF83C
&arr[0][1] == 004FF840
&arr[0][2] == 004FF844
&arr[0][3] == 004FF848
&arr[0][4] == 004FF84C
//一行内部地址连续,跨行也连续
&arr[1][0] == 004FF850
&arr[1][1] == 004FF854
&arr[1][2] == 004FF858
&arr[1][3] == 004FF85C
&arr[1][4] == 004FF860
&arr[2][0] == 004FF864
&arr[2][1] == 004FF868
&arr[2][2] == 004FF86C
&arr[2][3] == 004FF870
&arr[2][4] == 004FF874
&arr[3][0] == 004FF878
&arr[3][1] == 004FF87C
&arr[3][2] == 004FF880
&arr[3][3] == 004FF884
&arr[3][4] == 004FF888
数组越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
for (i = 0; i < 4; i++)
数组作为参数
数组传参传的是首元素的地址,arr[10]是个地址,指针变量
冒泡排序函数的错误设计
eg:输入10个整数,对数组进行排序
冒泡排序:两两相邻元素尽量比较
直接传数组名是错误的
void bubble_sort(int arr[10])//数组传参传的是地址
{
int sz = sizeof(arr) / sizeof(arr[0]);//arr是指针,大小是4 ,sz算下来是1
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;//每一趟比较的对数
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])//交换
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[10] = { 0 };
//输入
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
scanf("%d", &arr[i]);
}
//排序:冒泡排序、选择排序、插入排序、快速排序
//冒泡排序:bubble_sort();
bubble_sort(arr);//arr就是首元素地址
//输出
for (i = 0; i < sz; i++)
{
prin tf("%d ", arr[i]);
}
return 0;
}
数组名是什么?
数组名通常是数组首元素地址
int arr[10] = {0};
printf("%d\n", sizeof(arr));//输出40?
例外:
- sizeof(arr),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
- &arr,取出的是数组的地址。&数组名,数组名表示整个数组。
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);//00D8F718,数组名通常是数组首元素地址
printf("%p\n", &arr[0]);//00D8F718
printf("%p\n", &arr);//00D8F718,数组地址就是首元素地址
return 0;
}
[[数组地址.canvas|数组地址]]
冒泡排序函数的正确设计
void bubble_sort(int arr[10],int sz)//增加一个参数sz,在外部求好sz
{
//int sz = sizeof(arr) / sizeof(arr[0]);//sz不在内部求
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
//每一趟开始前,假设有序
int flag = 1;
//每一趟比较的对数
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1]) //交换
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)
break;
}
}
int main()
{
int arr[10] = { 0 };
//输入
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
scanf("%d", &arr[i]);
}
//排序:冒泡排序、选择排序、插入排序、快速排序
//冒泡排序:bubble_sort();
bubble_sort(arr, sz);//直接计算sz传入,不要在函数内部计算
//输出
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
数组应用__扫雷
- 9*9的棋盘,要识别周围8个格子是否有雷,怕遍历越界,所以多一圈11*11
- 需要2个数组,一个存放雷的信息,一个存放布置好的雷信息
- 数组是11*11,并且是字符数组
代码: 数组应用__扫雷