简单的来说,数组就是为了提高处理效率和把相同类型的的数据有秩序的组织起来,方便我们使用!
目录
使用数组的好处;
//输入五位学生的分数,并求出总分和平均分
这个是不使用数组前的一种方法,我们会发现,为什么怎么简单的一个函数,我们却要创建怎么多变量来去实现,还要冒着变量名输错的一个风险,这个时候我们就可以使用数组来去简化并实现这个程序!
这个时候,我们利用了数组这个知识,我们就发现,我们定义的变量名从五个变成了一个,这个就大大的简化了我们的程序!是不是很方便!
那又有小伙伴要问了,那我实现怎么简单的一个程序,为什么还是需要打怎么多的printf呢?能不能再让这个简单的代码,再次简化一点点呢?那我们接下来再看看这个代码!
那这个代码相比较上面那个代码是不是又简化了很多呢!那我们就分析一下这个代码、
原因:
首先我们先看一下设置的这个循环的三个表达式,第一个表达式的值其实就是让我们这个数组的访问从0开始,也就是下标0的一个设定,因为这是我们访问数组的必须的条件,第二个表达式i<=arr1[i]也就是i小于等于arr1[i]里面访问的值的时候(0<=1),进行下一个表达式的判断,那这个访问的值又是多少呢?因为我们前面分别给这个数组赋值为“1 2 3 4 5”所以这个arr1[i]访问的值是1(切记数组是从下标0开始访问的),当满足了这个表达式的判断的时候,就会进行下一个表达式,也就是i++,这个i++就是先使用后++,也就是这个循环的第一次循环是用0这个值进行,当执行下一次循环的时候就变成了0+1=1这个值!
当我们了解了这个循环的每一个表达式所要干什么事情的时候,就会很好理解这个代码了。
但是使用数组的一个前提就是,这个数组必须是相同类型的,简而言之就是数组擅长将相同类型的数据集中起来管理!然而数组不仅仅只有int类型也有double类型的数组,可以根据自己的需求,选择相对应的类型!一个重要的点就是数组是从下标0开始访问的,接下来我会讲什么是下标!
下标是一个符号,也可以叫做下标运算符 ‘ [ ] ’
然而我们访问数组里面的元素就是根据下标运算符来进行访问的,但是,我们一般访问数组的内容是从下标0开始的!
可以看看下面的代码
遍历;
遍历很简单,就是像上面这样,按顺序逐渐查看每一个数组的内容!
数组的初始化;
对于初始化单独来说,我希望大家都有一个好习惯,那就是,每当我定义一个变量的时候,我都希望大家去初始化为0或者去赋值一个自己需要的值!
那接下来讲讲数组的初始化:
数组的初始化就是在大括号中 ‘ { } ’ 用逗号分隔,并逐一赋值。
初始化可以分为三点,分别就是完全初始化,不完全初始化和初始化为零。
那下面还有几个关于数组初始化的点:
数组的复制;
我们会惊讶的发现,我的arr2的值明明是初始化为0的啊,但为什么又能打印出来值呢?
因为这就叫数组的复制,程序中的第一个for语句的作用就是把arr1的值依次赋值给了arr2的值里面!这里要注意的点就是 C语言不支持使用基本赋值运算符 = 为数组赋值 像arr2=arr1这种赋值就是错误的!!
输入数组元素的值;
对于数组的输入,也一定要加上取地址符号&!
对数组的元素进行倒叙排列;
定义一个数组,我们来对他进行倒叙排列!
分析:
我们将进行0与6之间的数组内容交换,1与5之间的内容交换,2与4之间的内容交换!
接下来我们将实现这个代码:
我们想要交换两个值的时候,必须要使用一个额外的变量,而这个temp就是我们设置的一个额外的变量。
然后和大家分享一下代码,希望大家可以自己再研究一下:
#include <stdio.h>
int main(void)
{
int i = 0;
int arr[7] = { 0 }; //初始化为0
for (i = 0; i < 7; i++) //写一个循环,依次输入arr[7]里面的值
{
printf("arr[%d]:", i);
scanf("%d", &arr[i]);
}
for (i = 0; i < 3; i++) //实现倒叙的一个循环
{
int temp = 0; //创建一个temp的变量,初始化为0
temp = arr[i]; //这个表达式是将arr[i]的值赋值给temp里面,因为是三次循环,所以arr数组的前三个值都在temp里。
arr[i] = arr[6 - i]; //因为arr[i]的值是赋值给了temp。我们可以理解为现在arr[i]里面的值是空的,然后把arr[6-i]也就是
//数组arr[6],arr[5],arr[4]的值赋值给arr[i],实际上就是arr[0],arr[1],arr[2]。
arr[6 - i] = temp; //因为arr[i]=temp,arr[i]=arr[6-i],所以arr[6-i]=temp。简单的交换律
}
puts("倒叙排列了!");
for (i = 0; i < 7; i++)
{
printf("arr[%d]:%d\n", i, arr[i]);
}
return 0;
}
对象式宏;
一般情况下,我们输入五位同学的变量的时候,是不是可以直接就定义一个5这个常量,但是不防止意外情况,假如有一天,我们需要快速的改成10位,20位的时候,我们是不是就又要改成20这个常量呢?不仅要改数组的还要改循环的,是不是很麻烦,这个时候我们就需要对象式宏
与上面的代码做比较,我们会发现,这个代码多了一个#define a 10 循环中的5也变成了a。这是为什么呢?这个就是使用了#define 指令 (#define directive)该指令的一般形式如下:
它的原理和文字处理或者编译器的替换处理是一样的,在将该指令之后的a替换b的基础上,再执行编译与执行处理。
在#define中,a就是宏名,一般情况下,宏名的首字母是可以大写的,这是为了区分变量名。
然而我们定义了#define的时候,再想要改人数的时候,就会很简单,我们只要在#define a 后面把原来的数字改成自己所需要的数字就行了!
使用宏的好处也是很有明显的,宏不仅能够在一个地方统一管理,而且通过为常量的定义名称,还可以使用程序阅读起来更简单容易。
注意:不要在程序中直接使用数值,最好能够通过宏的形式定义出它们的名称,定义宏的时候,也不要忘记加注释,这样会更方便代码的阅读!
对象式宏并不能够用来替换字符串常量和字符串面量中的部分内容,也不能用来替换变量名等标识符的部分内容。
数组元素的最大值和最小值;
#include <stdio.h>
define a 5 //定义为五个学生
int main(void)
{
int i = 0;
int arr[a] = { 0 }; //用defile定义的学生人数 a为5 a = 5
int max = 0; //最大值
int min = 0; //最小值
printf("请输出%d同学的分数:\n", a);
for (i = 0; i < a; i++)
{
printf("%2d号:", i + 1);
scanf("%d", &arr[i]);
}
min = max = arr[0]; //将第一个arr的值分别赋值到最大值和最小值。
for (i = 1; i < a; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
if (arr[i] < min)
{
min = arr[i];
}
}
printf("最高分:%d\n", max);
printf("最低分:%d\n", min);
return 0;
}
分析:
表达式:min = max = arr[0];在c语言中会经常使用这种赋值方式,例如使用a=b=0这个表达式,就可以把0同时赋值给a和b。
然后再看一下下面的循环就出最大值和最小值。因为一开始是把arr[0]的值分别赋值了最大值和最小值,也就是说,这个arr[0]是判断最大值和最小值的判断标准,所以这个循环是从1开始的,分别从数组的第二个值与第一个值进行比较,以此类推,最小值也是。
元素数组的个数;
输入学生的分数,并求出分布式用*的形式表示出了。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define NUMBER 80
int main(void)
{
int i = 0;
int j = 0;
int num = 0; //实际上的学生
int tensu[NUMBER] = { 0 }; //学生的分数
int bunpu[11] = { 0 };
printf("请输入学生的人数:");
do
{
scanf("%d", &num);
if (num<1 || num>NUMBER) //num的值小于1或者大于80才能进入if语句
{
printf("\a请输入1-%d的数:", NUMBER);
}
} while (num<1 || num>NUMBER);
printf("请输入%d人的分数:\n", num);
for (i = 0; i < num; i++) //此时我num的值是15
{
printf("%2d号:", i + 1);
do
{
scanf("%d", &tensu[i]);
if (tensu[i] < 0 || tensu[i]>100) //输入的值小于0或者大于100
{
printf("请输入1-到100的数字");
}
} while (tensu[i] < 0 || tensu[i]>100);
bunpu[tensu[i] / 10]++;
}
puts("\n----分布图----");
printf(" 100\n");
for (j = 0; j < bunpu[10]; j++)
{
putchar('*');
putchar('\n');
}
for (i = 9; i >= 0; i--)
{
printf("%3d-%3d:", i * 10, i * 10 + 9);
for (j = 0; j < bunpu[i]; j++)
{
putchar('*');
putchar('\n');
}
}
return 0;
}
分析:
在分析这个代码之前,我们先了解一个操作符‘ | | ’,这个是逻辑或操作符,意思是满足其中一个条件或者满足其中两个条件的时候,就为真,但是,两个条件都不满足的时候,就一定为假。先看看第一个循环 do while循环,这个循环有一个特点,就是先执行,后判断,程序开始执行后,我们需要输入一个数,这个数字代表的是学生人数,接着我们需要进入if语句的内部,但进这个内部的判断表达式是输入的num(学生的人数)的值要么小于1要么大于80(NUMBER 80)。所以我们就可以输入一个85这个值。进入if内部后,我们可以选择几位输入学生的分数,但是这个几位的上限最大为80且大于0。此时进行到这的时候,do while循环已经执行一轮了。因为我们输入num值为85的时候,已经满足了while语言的判断了。所以我们又要输入一个数字,但这个数字就是我们刚刚说的真正的学生人数,小于80大于1。此时我的num的值已经从85变成了15,然而15这个值显然不满足while循环的判断语句,因此中止循环。接着就是执行了‘ printf("请输入%d人的分数:\n", num); ’。
然后就进入了for循环,其实这个循环就是依次输入15同学的分数,最重要的一个表达式就是 bunpu[tensu[i] / 10]++;
这个表达式其实就是一个数组,一开始,这个数组就是一个int类型数组里面存放11的元素因为初始化为0,所以这个数组就是 int bunpu[11] = { 0,0,0,0,0,0,0,0,0,0,0, };因为这个表达式里面变成了[tensu[i] / 10],也就是我们输入的学生的分数除以10后++。然后我们调试一下看猜想是否正确
调试结果发现一开始数组的元素的值都是为0的
当我们输入17的时候,会发现数组的第二个元素确实增加了1。因此猜想正确
到了后面就是数组分数输入分布图,也就是从9从0慢慢递减!那么这个数组元素个数就分析完了!
例题:
1.读取数组中的数据个数和元素值并显示,各值之间用逗号和空格隔开,注意利用对象式宏来声明数组个数。
define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define tensu 4 //数据的个数
int main(void)
{
int i = 0;
int arr[tensu] = { 0 };
printf("数据个数:%d\n", tensu);
for (i = 0; i < tensu; i++)
{
printf("%d号:", i + 1);
scanf("%d", &arr[i]);
}
printf("{%d, %d, %d, %d}", arr[0], arr[1], arr[2], arr[3]);
return 0;
}
多维数组;
我们现在所学习的数组元素大部分都是为int类型和double类型的,实际上,数组的元素可以是数组本身。
以数组作为元素的数组是二维数组。以二维数组为数组的就是三维数组,当然也可以生成更多的数组,二维数组以上的数组,统称为多维数组。
注意:多维数组是以数组为元素的数组
然而二维数组和一维数组的区别很容易发现:
二维数组就是由一个‘行’和‘列’组成的,其中的各元素纵横排列,至于访问是和一维数组是一样的,都是从下标0开始访问的!
和一维数组一样,多维数组的所有元素/所有构成元素内存在内存上内容是排列成一条直线的。构成元素排列时,首先末尾是从0 1 2 的顺序递增,开头也是0 1 2 的顺序递增!
二维数组的赋值和使用;
假设有四名同学,三门课程,分别考了两次试,求出总分并分别显示两次的分数;
#include <stdio.h>
int main(void)
{
int i = 0;
int j = 0;
int tenuse1[4][3] = { {91,63,78},{67,72,46},{89,34,53},{32,54,34} }; //四位同学考三次考试第一次的成绩
int tenuse2[4][3] = { {97,67,82},{73,43,46},{97,56,21},{85,46,35} }; //四位同学考三次考试第二次的成绩
int sum[4][3] = { 0 }; //总分
//两次分数的和
for (i = 0; i < 4; i++)
{
for (j = 0; j < 3; j++)
{
sum[i][j] = tenuse1[i][j] + tenuse2[i][j];
}
}
//显示第一次考试的成绩
puts("第一次考试的分数:");
for (i = 0; i < 4; i++)
{
for (j = 0; j < 3; j++)
{
printf("%4d", tenuse1[i][j]);
}
putchar('\n');
}
//显示第二次考试的成绩
puts("第二次考试的分数:");
for (i = 0; i < 4; i++)
{
for (j = 0; j < 3; j++)
{
printf("%4d", tenuse2[i][j]);
}
putchar('\n');
}
//显示总分
puts("总分:");
for (i = 0; i < 4; i++)
{
for (j = 0; j < 3; j++)
{
printf("%4d", sum[i][j]);
}
putchar('\n');
}
return 0;
}
先讲一下二维数组的赋值吧,因为不管是一维数组还是二维数组,我们访问都是从下标0开始的,当然赋值也从下标0开始的。所以我们赋值一般给一个大括号在大括号中在添加一个大括号赋值中间用逗号隔开每一轮赋值结束也用逗号隔开,以上述代码为例,依次从[0][0],[0][1],[0][2]开始赋值。 [0][0],[0][1],[0][2]分别是91,63,78。这个时候已经结束第一轮行列了,这个时候可以给大括号,进行下一轮赋值,依次类推!
二维数组的初始化和一维数组一样!
到这里,数组的内容就全部完成啦!内容又臭又长!希望大家可以仔细阅读!感谢各位!