数组的概念
1.数组是⼀组相同类型元素的集合:注意到数组不只是复数的集合还可以字符、字符串的集合;故数组所含特性:
a.有限性;b.无序性;c.可重复。
2.数组分为一维数组和多为数组,其中多维数组最常见的是二维数组。
3.二维数组是指数组的元素为一维数组,同理三维数组的元素为二维数组。
一维数组
创建
·一维数组的表达形式:type arr_name[常量值]。
·其中type是指数组要存元素的类型,arr-name是指定义数组名,[]中的常量值即定义数组的大小。
例如:int num[10]表示num[]中可以存放10个整型。
初始化
数组的初始化用大括号和逗号:
1.完全初始化:int num[4]={1,2,3,4}
2.不完全初始化:int num[4]=0;此时num的第一个元素被赋值为0,其余元素默认为0.
3.错误初始化:int num[4]={1,2,3,4,5};此时初始过多,数组越界。
4.省略大小初始化:int num[]={1,2,3,4};此时num的大小为4;
类型
数组是自定义的类型,去掉数组名留下的就是数组的类型,如:
int arr1[10];
int arr2[12];
char ch[5];
arr1数组的类型是 int [10];arr2数组的类型是 int[12];ch 数组的类型是 char [5]
下标
数组的下标是从0开始的。
例如:
int num[4]={1,2,3,4};
数组 | 下标 |
---|---|
1 | 0 |
2 | 1 |
3 | 2 |
4 | 3 |
·在C语言中数组的访问提供了一个操作符 [] ,这个操作符叫:下标引用操作符。
int num[4]={1,2,3,4}
ptinf("%d",num[2])
上述代码将会在屏幕打印3。
同理我们可以运用[]完成对数组的输入和打印。
内存中的存储
一维数组在内存中是连续存储的,地址由小到大且每个元素间间隔4个(int的存储大小为4个字节,其他类型会有所不同)字节,此外数组名和第一个元素在内存中的地址相同。
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0; i<10; i++)
{
printf("&arr[%d] = %p\n ", i, &arr[i]);
}
return 0;
}
·%p用于打印地址。
上述代码的结果为:
数组元素个数计算
int num[10]={0};
int size=sizeof(num)/sizeof(num[0]);
size即为数组的元素个数,上述代码是通过计算数组的总存储大小除以单位元素存储大小来得到元素个数。
二维数组
创建
基本形式:type arr_name[常量值1][常量值2];
·注意到二维数组和一维数组的区别在于多了个[常量值2]。
·数组int num[3][4],可以理解为有三个一维数组int num[4],也可以理解成这个数组有三行四列(即每行四个元素)。
初始化
1.不完全初始化:int num[3][4]={1,2,3,};则该函数从第0行开始初始化,逐行进行,剩余的默认初始化为0.
2.完全初始化:int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}
3.按行初始化:int num[3][4]={{1,2},[3,4],[5,6]}。
行 | 列 | 数组 |
---|---|---|
0 | 0 | 1 |
0 | 1 | 2 |
0 | 2 | 0 |
0 | 3 | 0 |
1 | 0 | 3 |
1 | 1 | 4 |
1 | 2 | 0 |
1 | 3 | 0 |
2 | 0 | 5 |
2 | 1 | 6 |
2 | 2 | 0 |
2 | 2 | 0 |
4.二维数组初始化时可以省略行的大小但不能省略列的大小。
下标
二维数组的行和列也是从0开始数的。
int num[3][2]={1,2,3,4,5,6};
printf("%d",num[1][1]);
上述代码会打印4在屏幕上。
输入和输出
与一维数组的输入输出不同:一维数组只需要一个for循环数组的大小,依次输入和输出。二维数组则需要for循环行的大小嵌套for循环列的大小再依次输入输出。
内存中的存储
与一维数组相同,二维数组在内存中也是连续存储的,从第0行第0列开始,逐行存储。
变长数组
C99之前数组的大小必须是常量而C99之后的数组大小可以是变量,称之为变长数组。例如:
int arr1[10];
int arr2[3+5];
int arr3[] = {1,2,3};//正常数组
int n = a+b;
int arr[n];//变长数组
变长数组的特点是不能初始化,只有程序开始时才确定数组的大小,而不是说能够任意的改变数组的大小。这样的数组的好处就是可以节省内存空间,让程序效率更高。
数组运用
广告
#include <string.h>
#include <windows.h>
int main()
{
char arr1[] = "welcome to c++!!!!!!!";
char arr2[] = "*********************";
int left = 0;
int right = strlen(arr1)-1;
while (left<=right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);//休眠,单位是毫秒
system("cls");//用来执行系统命令的
left++;
right--;
}
printf("%s\n", arr2);
//char arr[] = "abc";
//printf("%d\n", strlen(arr));
return 0;
}
上述代码中Sleep是让代码休眠1000ms再运行,system则是用于执行系统命令的,命令cls就是清理屏幕。需要注意的是system是windows.h下的库函数。
二分查找
运用范围:在一个升序数组中找一个数在数组的位置,运用二分查找的效率比逐个查找的效率高出很多。
例如:
#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 = 7;//要找的数字
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\n", mid);
else
printf("找不到\n");
}
值得注意的是mid并不是写成(left+right)/2而是left+(right-left)/2目的是防止left+right过大,int识别失败。