数组的概念
数组是一组相同类型元素的集合
1.数组中存放的元素是一个或者多个,但是数组的元素不能为0;
2.数组中存放的多个元素,类型是相同的,例如int ,char
而我们所说的变量中就只有一个元素,
例如 int a = 0;char b =’ f '。
一维数组的创建和初始化
数组创建
一维数组创建的基本语法是:
type arr_name [常量值];
存放在数组中的值被叫做数组的元素,数组在创建时可以指定数组的大小(元素的个数) 和 数组元素的类型
type 是指数组中存放的值的类型,可以是char int short float double,也可以是自定义的类型;
arr_name 是指数组的名字,这个名字根据实际情况设置,起的有意义就可以了;
[ ] 中的常量值是用来指定数组的大小的,根据实际情况来设定。
下面创建几个数组:
int arr[20];
char ch[8];
数组的初始化
在数组创建时,我们需要给定一些初始数值,这种就被称为初始化。
数组的初始化一般使用大括号,将选定的类型的数据放在大括号中。
数组的类型
数组也是有类型的,数组算是一种自定义类型,去掉数组名留下的就是数组的类型
int arr1[10];
int arr2[8];
char ch[10];
arr1的类型为 int [10]
arr2的类型为 int [8]
ch的类型为 char [10]
而数组元素的类型就是type的类型。
一维数组的使用
数组下标
C语言规定数组是有下标的,下标是从0开始的,
也就是说如果数组有n个元素,那么最后一个数组的下标为n-1
下标就相当于数组元素的编号
int arr [10]={1,2,3,4,5,6,7,8,9,10};
数组 | 下标 |
---|---|
1 | 0 |
2 | 1 |
3 | 2 |
4 | 3 |
5 | 4 |
6 | 5 |
7 | 6 |
8 | 7 |
9 | 8 |
10 | 9 |
在C语言中数组的访问提供了一个操作符**[ ],叫做下标引用操作符**。
有了这个操作符,我们能够轻松的访问到数组的元素
例如:我们访问下标为7的元素,我们就可以使用arr[7],想要访问下标是3的元素,就可以使用arr[3],如下代码:
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;
}
输出的结果为
数组元素的输入与输出
如果我们想要访问整个数组的内容,就需要产生所有的元素的下标即可,我们只需要运用for循环就可以了,代码如下:
int main()
{
int arr[10] = { 0 };
int n = 0;
//输入
for (n = 0; n < 10; n++)
{
scanf("%d", &arr[n]);
}
//输出
for (n = 0; n < 10; n++)
{
printf("%d ", arr[n]);
}
return 0;
}
输入数据的结果:
一维数组在内存中的存储
1.内存:
电脑的内存分为多种,有4G,8G,16G,32G,64G(计算机处理的数据。都要加载到内存中处理)
内存会被划分为1一个个的内存单元(大小为1个字节),然后给每个内存单元都编上号
即编号地址C语言中的指针
2.为了了解数组在内存中的存储,我们就要知道数组元素的地址:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int n = 0;
for (n = 0; n < 10; n++)
{
printf("&arr[%d]=%p\n", n, &arr[n]);
// &--取地址操作符 %p--打印地址的数据类型 (&&--并且)
}
return 0;
}
其中 &–取地址操作符 (&&–并且) %p–打印地址的数据类型
输出的结果为:
从输出的结果可以看出:
1.数组随着下标的增长,地址是由小到大变化的;
2.每相邻的两个元素之间相差为4(因为一个整型是4个字节);
得出的最后结论就是:数组在内存中是连续存放的
sizeof计算数组元素的个数
sizeof是C语言中的一个关键字,是可以计算类型或者变量大小/长度的,单位是字节,其实sizeof也可以计算数组的大小
比如:
int main()
{
int arr[10] = { 0 };
printf("%d\n", sizeof(arr));
return 0;
}
这里输出的结果为40(10x4),计算的是数组所占的空间的总大小。
我们又知道数组所有元素的类型都是相同的,那只要计算出一个元素所占字节的个数,数组的元素个数就能算出来。我们选择第一个元素算大小就可以。
int main()
{
int arr[10] = { 0 };
printf("%d\n", sizeof(arr[0]));//计算一个元素的大小,单位是字节
return 0;
}
最后我们就能计算数组的元素个数:
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n",sz );
return 0;
}
这里的结果是:10,表达数组有10个元素。
数组的元素个数计算公式:sizeof(arr) / sizeof(arr[0])
二维数组的创建与初始化
二维数组的概念
如果我们把一维数组做为数组的元素,这时候就叫二维数组,
二维数组作为数组元素的数组称为三维数组,
二维数组以上的数组统称为多维数组
二维数组的创建
二位数组的语法如下:
type arr_name[常量值1][常量值2]
前面的内容与一维数组一致,
而[常量值1]—行数 [常量值2]—列数
二维数组的初始化
在创建变量或者数组时,给定一定的初始值,被称为初始化。
像一维数组一样,也是使用大括号来初始化的
1.不完全初始化
依次初始化每一行,当不够的时候,剩余的元素初始化为0
int arr1[3][5]={1,2};
int arr2[3][5]={0};
2.完全初始化
int arr3[3][5]={1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
3.按照行初始化
如果想要几个数据在同一行,则可以在{}下再添加{}
int arr4[3][5]={{1,2}{3,4}{5,6}};
4.初始化时省略行,但是不能省略列
数组如果初始化了,也可以省略掉数组的行,编译器会根据数组的初始化内容来确定数组的大小
int arr4[][5]={1,2,3};//一行
int arr5[][5]={1,2,3,4,5,6,7};//二行
int arr6[][5]={{1,2}{3,4}{5,6}};//三行
二维数组的使用
二维数组的下标
二维数组访问也是使用下标的形式的,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。
C语言规定,二维数组的行是从0开始的,列也是从0开始的 如下所示:
int arr[3][5]={1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
图中最右侧绿色的数字表示行号,第一行蓝色的数字表示列号,都是从0开始的。
比如:我们说:第二行,第四列,快速能定位出7。
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
printf("%d\n", arr[2][4]);
return 0;
}
输出的结果为:
二维数组的输入与输出
int main()
{
int arr[3][5] = { 0 };
int a = 0;
int b = 0;
//输入
for (a = 0; a < 3; a++)//产生行号
{
for (b = 0; b < 5; b++)//产生列号
{
scanf("%d", &arr[a][b]);//输入数据
}
}
//输出
for (a = 0; a < 3; a++)//产生行号
{
for (b = 0; b < 5; b++)//产生列号
{
printf("%d ", arr[a][b]);//输出数据
}
printf("\n");
}
return 0;
}
输入和输出的结果:
二位数组在内存中的存储
跟一维数组一样,我们为了研究二维数据在内存中的存储方式,我们也可以打印出数组所有元素的地址。
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
int a = 0;
int b = 0;
for (a = 0; a < 3; a++)
{
for (b = 0; b < 5; b++)
{
printf("&arr[%d][%d]=%p\n", a, b, &arr[a][b]);
}
}
return 0;
}
输出的结果:
从输出的结果可以得出:
1.每一行内部的各个元素都是相邻的,地址之间相差四个字节
2.跨行位置处的两个元素(如:arr[0][4]和arr[1][0])之间也差四个字节
所以二维数组的每个元素都是连续存放的
如下图所示:
arr[0]为第一行数组名——arr[0][b]
arr[1]为第二行数组名——arr[1][b]
arr[2]为第三行数组名——arr[2][b]
C99的变长数组
在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量,常量表达式,或者如果我们初始化数据的话,可以省略数组大小。
在C99中给一个变长数组的新特征,允许我们可以使用变量指定数组大小
int n = a+b;
int arr[n];
上面代码中,数组arr就是变长数组,因为它的长度取决于变量n的值。
变长数组的根本特征,就是数组长度只有运行时才能确定,所以变长数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定一个估计的长度,程序员可以在运行时为数组分配精确的长度。但变长数组的意思是数组的大小可以使用变量来指定的,在程序运行的时候,根据变量的大小来指定数组的元素个数,而不是说数组的大小是可变的。数组的大小一旦确认就不能再变化的。
数组练习
多个字符由两边向中间汇聚
1.strlen和sizeof的区别:
char ch = 'a b c'//a,b,c,/0
strlen–求字符串长度(/0之前的元素个数) 为3 使用时要包含头文件#include<string.h>
sizeof–求字符串占空间的大小(包含/0) 为4
2.代码:
#include<windows.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char arr1[] = "welcome to YueYang!!!";
char arr2[] = "*********************";
int left = 0;
int right = strlen(arr1) - 1;
printf("%s\n", arr2);
while (left <= right)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right--;
system("cls");
printf("%s\n", arr2);
}
return 0;
}
3.函数介绍:
Sleep(常数值)–睡眠,表示代码运行暂停,常量值表示睡眠的时间,单位是毫秒;使用时要包含头文件#include<windows.h>
system–system是库函数,执行系统指令,例如:“cls”-清理控制台屏幕信息;使用时要包含头文件#include<stdlib.h>
二分查找
1.使用限制:在一个**升序(按顺序)**的数组中查找指定的数字n;
2.代码:
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int key = 0;
scanf("%d", &key);
int left = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int right = sz - 1;
int mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (key == arr[mid])
{
printf("找到了,下标为%d\n", mid);
break;
}
else if (key > arr[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
if (left > right)
{
printf("找不到\n");
}
}
return 0;
}
一次折半的过程包含下面几个步骤:
①确定被查找的范围:
②确定被查找范围的左右下标:
③根据左右下标来确定中间的下标:
④然后将中间下标所对应的数组的元素和要找的元素进行比较:
⑴找到了:结束循环
⑵找不到:根据大小关系,确定新的查找范围
3.如果left和right比较大的时候可能存在空间问题,所以使用下面的方式来书写会更好:
mid = left+ (right - left) / 2