C语言数组
强调:数组也是一种数据类型;
例如:
int arr[10];
它的数据类型表示为:int[10]
本篇博客代码: (点击文字即可进入)
一、一维数组的创建和初始化
1、数组的创建
数组是一组相同类型元素的集合
数组的创建方式:
type_t arr_name [const_t];
//type_t 是指数组元素的类型
//arr_name 是指数组名
//const_t 是一个常量表达是,用来指定数组的大小
数组创建的实例:
//例1:
int arr1[10];
//例2:
int count = 10;
int arr2[count]; //这种创建数组的方式,叫创建变长数组,
//是在c99标准以后加入的,
//在gcc编译器下可以这样创建,vs下不支持这种方式
//例3:
char arr3[10];
float arr4[2];
double arr5[20];
注意:
数组创建,在c99标准之前,[]中要给一个常量才可以,不能使用变量。在c99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。
2、数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理的初始值(初始化)。
例:
int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {'a', 98, 'c'};
char arr5[] = {'a', 'b', 'c'};
char arr6[] = "abcdef";
数组在创建的时候如果想不指定数组的确定大小就得初始化。数组的元素个数根据初始化的内容来确定。
但是如下代码要区分,内存中是如何分配的。
char arr1[] = "abc";
char arr2[3] = {'a', 'b', 'c'};
对于arr1来说里面存放的是:‘a’ ‘b’ ‘c’ ‘\0’
对于arr2来说里面存放的是:‘a’ ‘b’ ‘c’
3、一维数组的使用
数组元素的访问可以使用下标访问符:[ ],下标引用操作符。它其实就是数组访问的操作符。
#include <stdio.h>
int main()
{
int arr[10] = { 0 }; //数组的不完全初始化 ,数组内容全部初始化为0
//计算数组中元素的个数
int sz = sizeof(arr) / sizeof(arr[0]);
//对数组内容赋值,数组的使用是通过小标来进行访问的,下标从0开始。所以:
int i = 0; //做下标
for (i = 0; i < sz; i++)
{
arr[i] = i;
}
//输出数组的内容
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
总结
1、数组是使用下标来访问的,下标是从0开始。
2、数组的大小可以通过计算得到。
4、一维数组再内存当中的存储方式
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
arr[i] = i;
}
for (i = 0; i < sz; i++)
{
printf("%p\n", &arr[i]);
}
return 0;
}
结论:
随着数组下标的增长,元素的地址,也在有规律的递增。
数组在内存中是连续存放的
二、二维数组的创建和初始化
1、二维数组的创建
#include <stdio.h>
int main()
{
//二维数组的创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
return 0;
}
2、二维数组的初始化
//二维数组的初始化
int arr4[2][2] = { 1,2,3,4 };
int arr5[2][2] = { {1,2},{3,4} };
int arr6[][4] = { {2,3},{4,5} }; //二维数组如果有初始化,行可以省略,列不能省略
3、二维数组的使用
二维数组是通过两个下标进行访问数组元素,行下标和列下标
#include <stdio.h>
int main()
{
//二维数组元素的访问
int i = 0, j = 0;
int arr[3][4] = { 0 };
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
arr[i][j] = i * 4 + j;
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}
4、二维数组在内存当中的存储方式
#include <stdio.h>
int main()
{
//二维数组元素的访问
int i = 0, j = 0;
int arr[3][4] = { 0 };
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%p\n", &arr[i][j]);
}
}
return 0;
}
输出结果:
二维数组在内存中也是连续存放的:
三、数组越界
数组的下标是有范围限制的。
数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1.
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。
例如:
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 0 };
for (i = 0; i < 12; i++)
{
arr[i] = i;
printf("%d ", arr[i]);
}
return 0;
}
程序运行时会报出这样的错误
四、数组作为函数参数
1、什么是冒泡排序
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
- 算法步骤
(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
(3)针对所有的元素重复以上的步骤,除了最后一个。
(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
90 21 132 -58 34
第一轮:
- 90 和 21比,90>21,则它们互换位置:
21 90 132 -58 34
- 90 和 132 比,90<132,则不用交换位置。
- 132 和 –58 比,132>–58,则它们互换位置:
21 90 -58 132 34
4)132 和 34 比,132>34,则它们互换位置:
21 90 -58 34 132
到此第一轮就比较完了。第一轮的结果是找到了序列中最大的那个数,并浮到了最右边。
比较时,每轮中第 n 次比较是新序列中第 n 个元素和第 n+1 个元素的比较(假如 n 从 1 开始)。
第二轮:
- 21 和 90 比,21<90,则不用交换位置。
- 90 和 –58 比,90>–58,则它们互换位置:
21 -58 90 34 132
- 90 和 34 比,90>34,则它们互换位置:
21 -58 34 90 132
到此第二轮就比较完了。第二轮的结果是找到了序列中第二大的那个数,并浮到了最右边第二个位置。
第三轮:
- 21 和 –58 比,21>–58,则它们互换位置:
-58 21 34 90 132
- 21 和 34 比,21<34,则不用交换位置。
到此第三轮就比较完了。第三轮的结果是找到了序列中第三大的那个数,并浮到了最右边第三个位置。
第四轮:
- –58 和 21 比,–58<21,则不用交换位置。
至此,整个序列排序完毕。从小到大的序列就是“–58 21 34 90 132”。从这个例子中还可以总结出,如果有 n 个数据,那么只需要比较 n–1 轮。而且除了第一轮之外,每轮都不用全部比较。因为经过前面轮次的比较,已经比较过的轮次已经找到该轮次中最大的数并浮到右边了,所以右边的数不用比较也知道是大的。
2、冒泡排序函数的错误设计
//方法1:
#include <stdio.h>
void bubble_sort(int arr[])
{
int sz = sizeof(arr) / sizeof(arr[0]); //计算数组中元素的个数,这样可以吗?
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 temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
bubble_sort(arr); //对arr进行升序排序
int i = 0;
//打印排序后的数组
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
对程序进行调试后发现在bubble_sort()内部sz等于1
问题出现在数组传参上。下面介绍数组传参究竟传的是什么。
3、数组名是什么?
#include <stdio.h>
int main()
{
int arr[4] = { 1,2,3,4 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
printf("%d\n", sizeof(arr));
return 0;
}
结论:
1.sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
2.&数组名,取出的是数组的地址。&数组名,表示整个数组
除此1、2两种情况之外,所有的数组名都表示数组首元素的地址。
4、冒泡排序函数的正确设计
//方法2:
#include <stdio.h>
void bubble_sort(int arr[], int sz)
{
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 temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz); //对arr进行升序排序
int i = 0;
//打印排序后的数组
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
五、数组的实例
三子棋和扫雷,博主还在奋力赶稿中,完成第一时间告知大家,源码已经上传!!!
1、三子棋
三子棋链接: 请参照我的另一篇博客(点击文字即可进入)
三子棋链接: 源代码链接(点击文字即可进入)
2、扫雷
扫雷链接: 请参照我的另一篇博客(点击文字即可进入)
扫雷链接: 源代码链接(点击文字即可进入)
到这里这篇博客已经结束啦。
这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀