一维数组
数组的概念
为了能够存放多个相同类型的数组,就有了数组!!
数组是一组相同类型的元素的集合
数组一般分为一维数组和多维数组
数组在创建的时候可以指定数组的大小和数组的元素类型
数组的语法格式:type arr_name ----------
type指定的是数组中存放数据的类型,可以是char、short、int 、float
arr_name指的是数组的名字
[ ]中的常量值是用来指定数组的大小,根据实际需要来定义
数组是不需要取地址的
代码语言:javascript复制//type arr_name
//存放20个成绩
//int math[20];//数组有20个元素,每个元素的类型是Int
存放字符
//char ch[5];
//double arr[6];
int math[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};//完全初始化
int math[20] = { 1,2,3,4,5,6,7,8,9,10 };
char ch[5] = { 'a','b','c','d','e'};//不完全初始化,剩下的元素默认初始化为0
char ch[5] = "abc";
double arr[6] = {0.0};
int main()
{
int a = 10;
char ch = 'w';
double d = 0.0;
int arr[10] = { 0 };
//数组有没有类型
//数组的类型是什么?
//数组的元素类型是int
//数组arr的类型的类型是--------int[10]
//int arr1[10]和int arr2[5]数组类型是不一样的
return 0;
数组是有下标的,下标是从0开始的,假设有n个元素,那么最后一个元素的下标就是n-1
当数组为1 2 3 4 5 6
则对应的下标就是0 1 2 3 4 5 //数组元素的编号
通过下标找到对应的元素:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//arr[5] //通过下标找到对应的元素
printf("%d", arr[5]);
return 0;
}
输出结果是:6
查找元素时使用的arr[],,,这里的[]是 下标引用操作符
与上方面的int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };截然不同,45行的10是指定数组元素个数的,而47行的5是数组元素的下标
当数组进行初始化的时候,数组的大小可以忽略的,就是arr后面的方括号内可以不用填写数字 。
编译器会根据数组的初始化内容,自动计算数组的元素个数
用循环打印数组中的所有元素:
for循环
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i )
{
printf("%d ", arr[i]);
}
return 0;
}
while循环
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
while (i < 10)
{
printf("%d ", arr[i]);
i ;
}
return 0;
}
do while循环
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
do
{
printf("%d ", arr[i]);
i ;
} while (i < 10);
return 0;
}
打印自己输入数组的全部内容:
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
/*do
{
printf("%d ", arr[i]);
i ;
} while (i < 10);*/
for (i = 0; i < 10; i )
{
//输入10个元素放在数组里面,
scanf_s("%d ", &arr[i]);//arr[i]是整型元素,需要取地址,数组名才是地址
}
for (i = 0; i < 10; i )
{
//在打印数组中的元素
printf("%d ", arr[i]);
}
一维数组在内存中的存储
代码语言:javascript复制int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//打印这是个元素的地址
int i = 0;
for (i = 0; i < 10; i )
{
/*printf("%dn", arr[i]);*/ //现在不是打印数组的元素,而是所有数组的地址
printf("&arr[%d]=%pn", i,&arr[i]);//在上方数字的基础上添加&---取地址
//地址要用%p来打印,i对应的是%d ,
}
return 0;
return 0;
}
打印结果:
&arr[0]=0000004275FEF8A0
&arr[1]=0000004275FEF8A4
&arr[2]=0000004275FEF8A8
&arr[3]=0000004275FEF8AC
&arr[4]=0000004275FEF8B0
&arr[5]=0000004275FEF8B4
&arr[6]=0000004275FEF8B8
&arr[7]=0000004275FEF8BC
&arr[8]=0000004275FEF8C0
&arr[9]=0000004275FEF8C4
地址过于长,因为我们的配置是x64的环境
在64位的环境中地址是64bit位的,就比较长
为了观察方便,将配置环境该成x86的环境,就是32位的环境
调试后的结果:
&arr[0]=0081F984
&arr[1]=0081F988
&arr[2]=0081F98C
&arr[3]=0081F990
&arr[4]=0081F994
&arr[5]=0081F998
&arr[6]=0081F99C
&arr[7]=0081F9A0
&arr[8]=0081F9A4
&arr[9]=0081F9A8
这里显示的地址是16进制的
十进制的数字:0 1 2 3 4 5 6 7 8 9
十六进制的数字:0 1 2 3 4 5 6 7 8 9 10-a 11-b 12-c 13-d 14-e 15-f
十六进制中,逢十六进一,,,,,6c 4 个位上的c 4等用于12 4=16,满16进一,1 6=7,所以6c 4=70
所以上述的数组的地址都只相隔4
1个int类型的字节占4个字节
得出结论:
1.数组在内存中是连续存放的
2.随着数组下标的增长,地址也是由小(低)到大(高)变化
sizeof计算数组元素的个数
代码语言:javascript复制int main()
{
int a = 0;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%dn", sizeof(arr));//计算变量的长度,单位是字节
return 0;
}
输出结果是:
40
10个6元素都是int ,每个int的长度都是4,所以数组的长度为4*10=40
计算的是数组所占内存空间的总大小,单位是字节
代码语言:javascript复制int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int a = sizeof(arr) / sizeof(arr[0]);
printf("%d", a);
return 0;
;
}
sizeof(arr)是整个数组的长度
sizeof(arr[0])是单个元素的长度,每个元素的长度都相等,两个相除就可以得到数组里面元素的个数了
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i )
{
printf("%d", arr[i]);
}
return
在第24行直接令i<sz
二维数组
数组的创建
概念
将一维数组作为数组的元素,就是二维数组
将二维数组作为数组的元素,就是三维数组
二维数组以上的被称为多维数组
代码语言:javascript复制type name[行][列]
数组名字根据自己需求定义
float score[5][30]// 5个班,每个班30人的分数,都为小数
二维数组的初始化
代码语言:javascript复制int date[3][5] = {1,2,3,4,5,6,7,8};//不完全初始化
int date[3][5] = {0};//不完全初始化
int date[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};//完全初始化
我们希望1,2放在第一行,3,4放在第二行,5,6,放在第三行,应该如何做?
int date[3][5] = {1,2,3,4,5,6};
改变如下:
int date[3][5] = {{1,2},{3,4},{5,6}};
因为二维数组里面的元素是一维数组
二维数组在初始化的时候行可以省略,列不能省略
int date[][5] = {{1,2},{3,4},{5,6}};
二位数组的使用
数组名是地址
代码语言:javascript复制c语言默认行和列默认从0开始的
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
printf("%dn",arr[1][2]);
输出结果为4
printf("%dn",arr[1][2]);
输出结果为7
int main()
{
int arr[3][5] = { 0 };
int i = 0;
//输入
for (i = 0; i < 3; i )
{
int j = 0;
for (j = 0; j < 5; j )
{
scanf_s("%d", &arr[i][j]);
}
}
//输出
for (i = 0; i < 3; i )
{
int j = 0;
for (j = 0; j < 5; j )
{
printf("%d", arr[i][j]);
}
printf("n");
}
return 0;
}
二维数组在内存中的存储
二维数组行可以省略
代码语言:javascript复制二维数组的位置
int main()
{
int arr[3][5] = { 0 };
int i = 0;
for (i = 0; i < 3; i )
{
int j = 0;
for (j = 0; j < 5; j )
{
printf("&arr[%d][%d]= %pn",i,j ,&arr[i][j]);
}
}
return 0;
}
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
//1 2 3 4 5
//2 3 4 5 6
//3 4 5 6 7
int i = 0;
for (i = 0; i < 5; i )
{
int j = 0;
for (j = 0; j < 3; j )//将行和列置换过来
{
printf("%d", arr[j][i]);
}
printf("n");
}
return 0;
}
输出结果是:
123
234
345
456
567
变长数组:
在vs2020无法使用,但是在devc 可以使用
int main()
{
int n = 0;
int arr[n];
int i = 0;
for (i = 0; i < n; i )
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i )
{
printf("%d", arr[i]);
}
return 0;
}
int main()
{
int n = 0;
int arr[n];
int i = 0;
scanf("%d", &n);
for (i = 0; i < n; i )
{
arr[i]=6;
}
for (i = 0; i < n; i )
{
printf("%d", arr[i]);
}
return 0;
}
变长数组不能初始化,好处就是程序员可以为数组分配一个精确的长度
变长数组的意思就是:数组的大小可以使用变量来指定的
数组训练
代码语言:javascript复制#include <string.h>//一定要添加的头文件,对于stelen
#include <stdio.h>
int main()
{
//char arr[] = "abc";
//a b c
//0 1 2 3对应的下标,最右边的结尾c所对应的下标应该-1
char arr1[] = "hello bit!!!!!!";
char arr2[] = "###############";
int left = 0;
int right = strlen(arr1) - 1;//看5、6、7行理解为什么这么写
//数组的最右边应该从arr1数组的长度减一开始算
while (left<=right)//循环停止的条件
{
arr2[left] = arr1[left]; // arr2的左边等于arr1的左边
arr2[right] = arr1[right]; // arr2的右边等于arr1的右边
printf("%sn", arr2); // 再将改变后的arr2打印出来
left ; //left依次向右边走
right--; right依次向左边走
}
return 0;
}
若是想看到动态变化效果,改动如下:
添加睡眠时间1000毫秒,在44行
#include <stdio.h>
#include <string.h>
#include <wiindows.h>
int main()
{
char arr1[] = "hello bit!!!!!!";
char arr2[] = "###############";
int left = 0;
int right = strlen(arr1) - 1;
while (left<=right)//循环停止的条件
{
arr2[left] = arr1[left]; // arr2的左边等于arr1的左边
arr2[right] = arr1[right]; // arr2的右边等于arr1的右边
printf("%sn", arr2); // 再将改变后的arr2打印出来
Sleep(1000);//1000的单位是毫秒,休眠1000毫秒
left ; //left依次向右边走
right--; //right依次向左边走
}
return 0;
}
引用Sleep()需要引用头文件#include <windows.h>
在47行后面添加这么一串代码去//执行系统命令清理屏幕,使出现的代码只出现在第一行,清理控制台平屏幕的信息
system("cls");
改动如下:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <wiindows.h>
int main()
{
char arr1[] = "hello bit!!!!!!";
char arr2[] = "###############";
int left = 0;
int right = strlen(arr1) - 1;
while (left<=right)//循环停止的条件
{
arr2[left] = arr1[left]; // arr2的左边等于arr1的左边
arr2[right] = arr1[right]; // arr2的右边等于arr1的右边
printf("%sn", arr2); // 再将改变后的arr2打印出来
Sleep(1000);//1000的单位是毫秒,休眠1000毫秒
system("cls");//执行系统命令清理屏幕
left ; //left依次向右边走
right--; //right依次向左边走
}
return 0;
}
注意###//system()使用的话需要引用头文件:
#include <stdlib.h>
但是最后一次代码也被清除了
所以我们仍需做出改动:
int main()
{
char arr1[] = "hello bit!!!!!!";
char arr2[] = "###############";
int left = 0;
int right = strlen(arr1) - 1;
while (left<=right)//循环停止的条件
{
arr2[left] = arr1[left]; // arr2的左边等于arr1的左边
arr2[right] = arr1[right]; // arr2的右边等于arr1的右边
printf("%sn", arr2); // 再将改变后的arr2打印出来
Sleep(1000);//1000的单位是毫秒,休眠1000毫秒
system("cls");//执行系统命令清理屏幕
left ; //left依次向右边走
right--; //right依次向左边走
}
printf("%sn", arr2);
return 0;
}
在循环的结束末尾再次打印就好了
system("cls");这个代码仅仅只是清理屏幕,但是数组内的内容还在
因为数组里面的内容还在,再将内容打印一遍就出现最后的结果了
代码语言:javascript复制折半查找也叫二分查找
查找的前提条件是数据是有序的
通过下标选择中间元素
一次二分查找如下
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//输入一个数组
int k = 0; //定义一个变量
scanf_s("%d", &k);//输入要查找的值,假设是7
int sz = sizeof(arr) / sizeof(arr[0]); //得到数组的长度
int left = 0; // 左端下标
int right = sz-1;//左右下标确定,因为是从0开始的,所以右端下标要-1
while (left<=right)//当left<=right时,应该就同时指向同一个数//此处为循环的的条件
{
int mid = (left right) / 2; //下标的中间值
if (arr[mid] < k)//如果中间值对应的数小于想要查找的值,就从下标mid 1的后面开始寻找
{
left = mid 1;
}
else if (arr[mid] > k)
{
right = mid - 1;//如果下标是中间值所对应的数字大于要寻找的数字,那么下标右边的数字可以不用看了,直接从中间值左边的那一个下标所对应的数字看起,左边的那个数字为新的right
}
else
{
printf("找到了,下标是%dn", mid);
break; //找到了就break跳出循环
}
}
if (left > right)
{
printf("找不到n");
}
return 0;
}
如果left<=right一直满足,程序就会一直循环,直到找到你输入的值
思考:此处的while()里面的括号内能放1吗?
因为找不到就死循环了,找不到不会break
第二种写法:定义flag//定义flag为0,就是没找到,但是 如果找到了就定义flag成1,没找到依然为0
int main()
{
int flag = 0;//假设找不到为0
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//输入一个数组
int k = 0; //定义一个变量
scanf_s("%d", &k);//输入要查找的值,假设是7
int sz = sizeof(arr) / sizeof(arr[0]); //得到数组的长度
int left = 0; // 左端下标
int right = sz-1;//左右下标确定,因为是从0开始的,所以右端下标要-1
while (left<=right)//当left<=right时,应该就同时指向同一个数//此处为循环的的条件
{
int mid = (left right) / 2; //下标的中间值
if (arr[mid] < k)//如果中间值对应的数小于想要查找的值,就从下标mid 1的后面开始寻找
{
left = mid 1;
}
else if (arr[mid] > k)
{
right = mid - 1;//如果下标是中间值所对应的数字大于要寻找的数字,那么下标右边的数字可以不用看了,直接从中间值左边的那一个下标所对应的数字看起,左边的那个数字为新的right
}
else
{
printf("找到了,下标是%dn", mid);
flag = 1; //找到就为1
break; //找到了就break跳出循环
}
}
if (flag == 0)//如果变为0,就是没找到
{
printf("找不到");
}
return 0;
}
为什么这里写的是sizeof,而不是strlen,因为strlen是求字符串长度的,而这里的arr被int定义为整型,strlen只能针对字符串或者字符数组
用(left right) / 2去求平均值存在问题,那么如何求两个较大的数的平均值呢?
假设现在有两个数a和b,现在a>b,去求平均值,将a>b的那部分减下来,然后除以二,给b一部分,给a一部分,现在a=b现在a和b的值就是他们原先值的平均值,以后求平均值可以这么写
int num = a (b-a)/2