数组
1.数组的概念
数组是一组相同类型元素的集合
数组中存放的额是1个或者多个数据,但是数组元素个数不能为0;
数组分为一维数组和多维数组,多维数组中二维数组使用次数较多。
2.一维数组的创建和初始化
数组创建的基本语法:
type arr_name[常量值]
存放在数组中的值称为数组元素,数组在创建时可以指定数组的大小和数组的元素。
-
type指定的是存放数据的类型;
-
arr_name指的是数组名;
-
[常量值]指定数组大小。
int math[3]; char ch[6]; double score[9];
数组的初始化
int arr[5]={1,2,3,4,5};//完全初始化 int arr2[6]={1};//不完全初始化,第一个元素初始化为1,其余为0 int arr3[3]={1,2,3,4}//错误的初始化,溢出。
数组的类型
int arr1[10]; int arr2[12]; char ch[5];
arr1的类型是int [10]; arr2的类型是in [12]; ch的类型是
char [5].
3.一维数组的使用
数组下标是从0开始的,假设数组有n个元素,最后元素的下标为n-1,下标相当于数组元素的编号。
int arr[10]={1,2,3,4,5,6,7,8,9,10}
数组 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
“[]”是下标引用操作符,便于直接访问指定位置元素。
#include<stdio.h> int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,10}; printf("%d\n",arr[7]); printf("%d\n",arr[3]); return 0; }//输出8和4
若想访问整个数组的内容,利用循环语句。
定长数组的输入使用循环语句也可以实现。
4.一维数组在内存中的存储
利用简单程序依次打印数组元素的地址
#include<stdio.h> int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int i; for(i=0;i<10;i++) { printf("&arr[%d] = %p\n",i,&arr[i]); } return 0; }
从输出结果可知,随着下标的增长,地址是由小到大变化的,相邻元素的地址差为元素类型长度。【数组在内存中是连续存放的,且下标从小到大对应着地址的从小到大。】
5.sizeof计算数组元素的个数
sizeof是C语言中用来确定类型和计算变量大小的关键字,sizeof也可以计算数组的大小,单位是字节,是数组的长度*类型。
由上面的数学关系就可以计算数组元素个数
#include<stdio.h> int main() { int a[10] = {0}; int num = sizeof(arr)/sizeof(arr[0]); printd("%d",num); return 0; }
6.二维数组的创建
将一维数组视为一条被n等分的直线,那么二位数组就可简单视为由线到面的扩展,类比成一块规整的土地上的整齐车库。
type arr_name[常量值1][常量值2]
-
常量值1指行数;
-
常量值2指列数;
-
其余同一维数组。
例如:int arr[3] [3]
a[0] [0] | a[0] [1] | a[0] [2] |
---|---|---|
a[1] [0] | a[1] [1] | a[1] [2] |
a[2] [0] | a[2] [1] | a[2] [2] |
7.二维数组的初始化
二维数组的初始化也分为完全初始化和不完全初始化
不完全初始化
int arr[3] [3] = {1,2};
1 | 2 | 0 |
---|---|---|
0 | 0 | 0 |
0 | 0 | 0 |
int arr[3] [3] = {0}
0 | 0 | 0 |
---|---|---|
0 | 0 | 0 |
0 | 0 | 0 |
完全初始化
int arr[3] [3] = {1,2,3,2,3,4,3,4,5};
1 | 2 | 3 |
---|---|---|
2 | 3 | 4 |
3 | 4 | 5 |
按行初始化
int arr[3] [3] = { {1,2} , {2,3} , {3,4} };
1 | 2 | 0 |
---|---|---|
2 | 3 | 0 |
3 | 4 | 0 |
初始化时省略行(常量1),但绝不能省略列(常量2)
int arr1 [] [3] = {1,2,3};//初始化的值小于等于列数,则定义为一行。
int arr2 [] [3] = {1,2,3,4,5}
1 | 2 | 3 |
---|---|---|
4 | 5 | 0 |
int arr3 [] [3] = { {1,2} , {2,3} , {3,4} };
1 | 2 | 0 |
---|---|---|
2 | 3 | 0 |
3 | 4 | 0 |
8.二维数组的使用
二维数组的输入和输出类似于一维数组,使用循环的嵌套就可以实现。
#include<stdio.h> int main() { int arr[3] [5]={0}; int i = 0; for(i=0;i<3;i++) { int j = 0; for(j = 0;i<5,j++) { scanf("%d",&arr[i] [j]); } } for(i=0;i<3;i++) { int j = 0; for(j = 0;i<5,j++) { printf("%d",&arr[i] [j]); } printf("\n"); } return 0; }
9.二维数组在内存中的存储
#include <stdio.h> int main() { int arr[3][5] = { 0 }; int i = 0; int j = 0; for (i = 0; i < 3; i++) { for (j = 0; j < 5; j++) { printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]); } } return 0; }
存放情况同一维数组,按行数从小到大依次存放,第一行先存放,紧接着就是第二行元素……地址差仍是类型大小
【二维数组中的每个元素都是连续存放的】
10.C99中的变长数组
定长数组固定的大小只能使用常量、常量表达式,这就是抑制发展的局限性,所以在C99中给出了变长数组,允许使用变量来指定数组大小。
int n =a+b; int arr[n];
以上面的例子来说,数组长度长度取决于变量n,编译器无法先确定,只有在具体运行时才可以确定。
【变长数组的根本特征:数组长度只有在运行时才可确定,故变长数组不能初始化。】
但是,变长数组并不是指数组的大小可变,而是根据变量的大小来指定数组的元素个数。(仔细理解)
【数组的大小一旦确定就不能再变化。】
注:有些编译器并不支持变长数组(如VS2022)。
11.数组练习
1.多个字符从两端移动,向中间汇聚
就是优先显示边上的字符,逐个向中间显示
#include<stdio.h> int main() { char arr1[] = "hello from the other side!";//阿黛尔的歌,26个字符 char arr2[] = "--------------------------";//与上面字符数一致 int left = 0; int right = strlen(arr1)-1;//下标所以减一 while(left<=right) { Sleep(1000);//睡眠1秒,就是给点时间间隔 arr2[left] = arr1[left]; arr2[right] = arr1[right]; left++; right--; printf("%s\n",arr2); } return 0; }
2.二分查找(折半查找)简单实现
在升序数组中查找指定数字n,优先比较中间的数,确定范围,无此数的另一半直接不查找,在有此数的一半内继续此方法。
#include<stdio.h> int main() { int arr[] = {1,2,3,4,5,6,7,8,9,10}; int left = 0; int right = sizeof(arr)/sizeof(arr[0])-1; int key = 6; int mid = 0; int find = 0; while(left<=right) { mid = left+(right-left)/2; if(arr[mid] > key) right = mid-1; else if(arr[mid] < key) left = mid + 1; else { find = 1; break; } } if(1 == find) printf("找到此数,下标为%d",mid); else printf("没有此数!"); }