2023.07.27
数组
一批具有同名的同属性的数据就组成一个数组(array)。
数组是一组有序数据的集合;用一个数组名和下标来唯一的确定数组中的元素;数组中的每一个元素都属于同一个数据类型。
一维数组
定义一个一维数组形式:
类型说明符 数组名【常量表达式】
例如: char arr[3]={'a','b','c'} int a[10]={1,2,3,4,5,6,7,8,9,10} char arr[]="abcdefg"
注意:常量表达式中可以包括常量和符号常量,但是不能包含变量。常量表达式用来表示元素的个数,即数组长度。
引用一维数组形式:数组名[下标]
注意:下标是从0开始的,如果有一数组a[10],则数组中的元素分别为a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],是不存在数组元素a[10]的。
定义数组时[常量表达式]和引用数组元素时[下标]内的含义是不同的,前者表示包含的元素个数,后者表示的是对应序号的那个数组元素。
练习:对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,按要求逆序输出。
int main()
{
int arr[10]={};
int i=0;
for(i=0;i<=10;i++)
{
arr[i]=i;//使用循环依次对数组元素赋值
}
for(i=9;i>=0;i--)
{
printf("%d ",arr[i]);//使用循环逆序依次输出数组元素
}
return 0;
}
对很多相同类型的数据赋值,使用数组和循环能很方便的解决。
一维数组的初始化:
在定义数组的同时给各数组元素赋值,这称为数组的初始化。未被初始化的的数组元素,系统回自动把它们初始化为0。
对全部数组元素赋予初值:int a[10]={0,1,2,3,4,5,6,7,8,9}; 对全部数组元素赋值时,数据个数已经确定,此时[ ]内可以不用书写数组元素个数。
对部分数组元素赋予初值:int a[10]={0,1,2,3,4}; 只给前五个数赋值,后五个数字则赋0,数组长度和提供初值的个数不同时,[ ]内不能忽略不写常量表达式。
对全部数组元素赋予初值0:int a[10]={0,0,0,0,0,0,0,0,0,0}; 或int a[10]={0};
一维数组的存储:先初步了解,数组在内存中是连续存放的。
使用sizeof计算数组元素个数:
sizeof是C语言中的一个关键字,是可以计算类型或者变量的大小的,当然也可以计算数组的大小。
int main()
{
int a[10]={0};
printf("%d",sizeof(a));
return 0;
}
输出的结果为40,表示数组所占内存空间的总大小为40字节,一个数字所占内存空间为4个字节。
另外,若知道一个字节所占内存空间大小,就可以推出数组元素有几个。
int main()
{
int a[10]={0};
printf("%d",sizeof(a)/sizeof(a[0]));
return 0;
}
输出结果为10,表示数组元素个数为10个。
使用数组还能解决在之前比较困难实现的问题:
之前写过一道Fibonacci的问题,输出前四十个数,在这里使用数组解决,并直接输出第25个数。
int main()
{
int a[40]={1,1,0};
int i=0;
for(i=0;i<=38;i++)
{
a[i+2]=a[i+1]+a[i];
}
for(i=0;i<=39;i++)
{
printf("%d ",a[i]);
}
printf("第25个数为%d",a[24]);
return 0;
}
int main()
{
int num_1=1,num_2=1,num_3=0,i;
printf("%d\n%d\n ",num_1,num_2);
for(i=1;i<=38;i++)
{
num_3=num_2;
num_2=num_1+num_2;
num_1=num_3;
printf("%d\n",num_2);
}
return 0;
}
对比可以发现,在使用数组对所求Fibonacci数时,可以不用进行数据替换的工作,使用数组可以存储数据,可以直接使用前两个已经赋值的数字对下一个数字进行赋值。另外,可以在循环外面随意输出任意一个求得的数字。
若想使数据变得整齐输出,可以限制一行输出数据个数,
if(i%n==0) printf("\n");//,使用这个if语句控制换行,n为限制一行输出数据个数
有10个地区的面积,要求对它们按由小到大的顺序排列。
升序降序问题:这种问题为排序的问题,一般抽象成“对n个数按升序\降序排列”。
在这里先学习使用起泡法排序排升序(降序同理),后续在找时间归纳这种问题的解法。
起泡法排序基本思路:每次将相邻两个数进行比较,将较小的调到前面。每一轮比较排序,都会有一个最大的数“沉底”到最后面,而相对较小的数向前“浮起”,下一轮减少一次最后俩数的比较,依次规律进行下去。
得出一般规律为:如果有n个数,则要进行(n-1)趟比较。在第一趟中进行比较(n-1)次,······,第j趟中进行比较(n-j)次比较,······,第(n-1)趟进行比较1次。
int main()
{
int arr[10]={0},i,j,temp;
printf("输入十个地区的面积:");
for(i=0;i<10;i++)
scanf("%d",&arr[i]);
for(j=0;j<9;j++)//外循环控制比较的轮数,n个数就进行(n-1)轮的比较
{
for(i=0;i<9-j;i++)//内循环控制每轮比较的次数,第j轮就进行(n-j)次的比较
{
if(arr[i]>arr[i+1])
{
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
}
for(i=0;i<10;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
收获:
①懂得如何运用循环来代替多个printf和scanf,简化代码的书写。
②对排序循环体的书写,由于数组元素是从0开始的,在书写for循环时对于运行条件的书写需要谨慎思考。
③还有,我在书写时犯了一个错误,就是内外循环都是使用同一个变量i,这使得在测试的时候,发现只运行了一次外循环,我才发现,只设置一个变量i是不合理的,我将外循环的变量改设置成j,使得i和j的改变各不影响,循环顺利进行。
二维数组
二维数组常称为矩阵。将一维数组作为数组的元素,这时候就得到了二维数组。一般写成行和列的排列形式。
二维数组的一般形式:类型说明符 数组名[常量表达式][常量表达式]
例如:int arr[2][3] double arr[5][6] char ch[8][9] 先行后列的定义数组长度。
注意:用矩阵形式表示二维数组,是逻辑上的概念,能形象地表示出行列关系。但在内存中,和一维数组一样,各元素是连续存放的,不是连续的,而是线性的。
类似的,三维,四维数组在后面加上[常量表达式]即可。
二维数组的引用
二维数组元素的表达形式:数组名[下标][下标]
二维数组的初始化
C语言中,二维数组中元素排列的顺序是按行存放的,即在内存中先顺序存放第一行的元素,接着再存放第二行的元素。(即从左到右,从上到下)
赋值的时候也是如此。
①分行给二维数组赋初值
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}} 这种赋值方法比较的直观,按行赋值。
若对全部元素赋初值,则定义数组时对第一维的长度可以不指定,但第二维的长度不可以省略。
②将所有的数据写在同一个花括号内,按排列顺序进行赋初值。
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}
③对部分元素赋初值,可以对某行,或者某个元素赋初值。
int a[3][4]={{0,0,0,4},{5},{0,10}}
二维数组的输入和输出
借助现有代码,学习如何输出有规律的代码。
int main()
{
int arr[3][5] ;//= {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
int i = 0;
//输入
for(i=0; i<3; i++) //产生行号
{
int j = 0;
for(j=0; j<5; j++) //产生列号
{
scanf("%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;
}
依然是使用循环的嵌套来输出数组中的各个元素,需要换行可以在一个内循环的结束后进行一次\n的打印。
明天的事明天再说,今天的我超越昨日的我。