C语言入门Part7–数组篇
**关键字:**数组常见问题及注意事项总结,字符串定义,一维数组在内存中的存储,sizeof()
求数组长度的注意事项,sizeof()
的用法注意,sizeof()
和strlen()
的实例解析,一维数组的使用(冒泡排序及优化,选择排序,直接插入排序),二维数组的创建和初始化,二维数组打印:分别打印上三角 下三角 对称矩阵,二维数组的应用(三子棋,扫雷链接)
数组常见问题及注意事项总结
- 如果数组没有初始化,默认值为随机值。(局部数组)
- 数组的整体赋值只有一次机会,就是在初始化的同时
arr2=arr
也是错的,不能整体赋值 - 局部数组,是在什么时候确定大小的?
编译的时候 - 什么时候分配内存?
运行的时候 - 最大分配多大内存?
1M或2M取决于栈的大小(因为数组实在栈当中分配大小的,所以最大就是栈的大小) - 整体初始化 局部初始化arr[10]={1,2};其余为0
- arr[ ]其中[]里面只能放常量
注意
const int a=10;
int arr[a]={0};//错误
错误原因:const修饰的是常变量,本质来说还是一个变量,只是这个变量被限制不能改变数值了而已
#define SIZE 10;
int main()
{
int arr[SIZE]={0};//正确
...
}
推荐使用,后期若想改变数组大小就可以直接改变SIZE的值,便于代码的修改
字符串定义
char * p="abcd";
char arr[]="abcd";
char arr[5]="abcd";
char arr[5]={'a','b','c','d','\0'};
注意:打印时用%s
数组名:代表数组首元素的地址
一维数组在内存中的存储
int main()
{
int a = 0;
int b = 0;
int arr[3] = { 0 };
printf("a:%p\nb:%p\n",&a,&b);
for (int i = 0; i < 3; i++)
{
printf("arr[%d]:%p\n",i, &arr[i]);
}
return 0;
}
- 定义int a和int b,打印地址发现地址差16个字节,即中间空出两个int的字节,空出来的地址所占字节叫哨兵位,可以防止溢出
- 运行结果可知数组会分配连续的内存==> 数组在内存中的存储是连续的
sizeof()
求数组长度的注意事项
求数组长度公式len=sizeof(arr)/arr(arr[0]);
注意
- 数组在哪里定义公式就在哪里使用
- 一般数组名代表首元素的地址,但在两种情况下代表整个数组
1.sizeof(arr)代表整个数组的字节大小
2.&arr+1 - 数组的传参,如果传数组名过来,那么就会退化为指针
sizeof(指针)
不论指针是什么类型结果都为4
数组传参 void Show(int arr[])和void Show(int * arr)作用一样
int arr[4] = { 1, 2, 3 };
printf("%d ", sizeof(arr[4]));
执行结果是4,arr[4]越界但未报错,因为sizeof()
是在编译期间处理,看表达式结果结果将来会是什么类型
拓展:sizeof()
的用法注意
int a =10;
printf("%d %d", sizeof(++a),a);//结果 4 10
结果分析:因为sizeof()
的结果是在编译期间确定的,里面的表达式并不会执行,所以最后a还是10
printf("%d ", sizeof(1+3.2));//结果为8,默认3.2double类型
printf("%d ", sizeof(1+3.2f));//结果为4,加f表flout
结果分析:sizeof()
默认求值结果是表达式中占字节大的结果
拓展:sizeof()
和strlen()
的实例解析
char str1[100]="abcdef";
char str2[]="abcdef";
char * str3="abcdef";
char str4[100]="abcdef\0xyz";
char str5[]="abcdef\0xyz";
char * str6="abcdef\0xyz";
char str7100]="abcdef\n\0xyz";
char str8[]="abcdef\n\0xyz";
char * str9="abcdef\n\0xyz";
printf("%d,%d\n",sizeof(str1),strlen(str1));//100 6
printf("%d,%d\n",sizeof(str2),strlen(str2));//7(还算了默认自己加的\0) 6
printf("%d,%d\n",sizeof(str3),strlen(str3));//4(sizeof(指针)都是4) 6
printf("%d,%d\n",sizeof(str4),strlen(str4));//100 6
printf("%d,%d\n",sizeof(str5),strlen(str5));//11(还算了默认自己加的\0) 6
printf("%d,%d\n",sizeof(str6),strlen(str6));//4 6
printf("%d,%d\n",sizeof(str7),strlen(str7));//100 7
printf("%d,%d\n",sizeof(str8),strlen(str8));//11(还算了默认自己加的\0) 7
printf("%d,%d\n",sizeof(str9),strlen(str9));//4 7
一维数组的使用
实例1 冒泡排序法
#include<stdio.h>
void BubbleSort(int arr[],int len)
{
int i = 0;
for (i = 0; i < len - 1; i++)//控制趟数
{
for (int j = 0;j < len-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 i = 0;
int arr[] = { 12,4,6,9,33,56,77 };
int len = sizeof(arr) / sizeof(arr[0]);
BubbleSort(arr,len);
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
冒泡优化
#include<stdio.h>
void BubbleSort(int arr[],int len)
{
int i = 0;
int count = 0;//判断是否交换,未交换说明有序,有序则可直接跳出
for (i = 0; i < len - 1; i++)//控制趟数
{
count = 0;
for (int j = 0;j < len-1-i ; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
count = 1;
}
}
if (count == 0)
{
break;
}
}
}
实例二 选择排序
void SelectSort(int arr[],int len)
{
int i = 0;
int j = 0;
for (i = 0; i < len - 1; i++)
{
for (j = i + 1; j < len; j++)
{
if (arr[i] > arr[j])
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
实例三 直接插入排序(越有序越快)
void InsertSort(int arr[],int len)
{
for (int i = 1; i < len ; i++)
{
int tmp = arr[i];
for (int j = i - 1; j >= 0; j--)
{
if (tmp < arr[j])
{
arr[j + 1] = arr[j];
}
else
{
break;
}
}
arr[j + 1] = tmp;
}
}
二维数组的创建和初始化
arr[][] 二维数组形式
arr[3][4]={0}; 三行四列 整体初始化为零
int arr[2][2]={1,2,3,4};等价于 int arr[2][2]={{1,2},{3,4}};
二维数组初始化注意事项
- 不可以同时不写行数和列数
- 可以只写列数,编译器会根据列数确定行数 但是行数不能省略
- 二维数组的内存也是连续的 二维数组是特殊的一维数组
- 二维数组名还是代表数组首元素地址,但是此时的首元素是一个一维数组的地址
== 》 所以需要定义一个指向数组的指针,即数组指针
arr[3][3]={1,2,3,4,5,6,7,8,9} ;
int (*p)[3]=arr;
-
二维数组传参要么写数组名,要么传数组指针。
int * p[3];
指针数组 存放指针的数组 -
[]
自带解引用arr[i]
就相当于*(arr+i)
-
指针的加法
int *(arr+i)
相当于加i*sizeof(int)
-
二维数组的初始化 循环嵌套
-
little tip:
%-2d
两位数左对齐打印
二维数组打印:分别打印上三角 下三角 对称矩阵
上三角
void UpAngle(int arr[][5], int row, int col)
{
int m = 1;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (i<=j)
{
arr[i][j] = m;
m++;
}
else
{
arr[i][j] = 0;
}
}
}
}
int main()
{
int arr[5][5] = { 0 };
UpAngle(arr, 5, 5);
return 0;
}
下三角
void UpAngle(int arr[][5], int row, int col)
{
int m = 1;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (i>=j)
{
arr[i][j] = m;
m++;
}
else
{
arr[i][j] = 0;
}
}
}
}
对称
void SymMatrix(int arr[][5], int row, int col)
{
int count = 1;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (i<=j)
{
arr[i][j] = count++;
}
arr[j][i] = arr[i][j];
}
}
}
数组应用实例
由于篇幅原因将二维数组应用实例放置以下博客:
三子棋
https://blog.csdn.net/qq_43360037/article/details/97668012
扫雷
https://blog.csdn.net/qq_43360037/article/details/97697689
扫雷进阶版
https://blog.csdn.net/qq_43360037/article/details/100412331