5.1数组简介
说明数组的概念的及其作用的最好方法,是通过一个例子,来说明使用数组后程序会变得非常简单
5.1.1 不用数组的程序
如何声明一个数组
数据类型 数组名称[长度];
- C语言中的数组初始化是有三种形式的
数据类型 数组名称[长度n] = {元素1,元素2…元素n};
数据类型 数组名称[] = {元素1,元素2…元素n};
数据类型 数组名称[长度n]; 数组名称[0] = 元素1; 数组名称[1] = 元素2; 数组名称[n] = 元素n+1;
5.1.2 什么是数组
- 字符串碰到了零,就意味着字符串结束了,是一个标
标准库提供一个memset把字符数组清零 - 数组是一组数目固定,类型相同的数据项,数组中的数据项称为元素。
int numbers [10];//声明数组 类型名称 数组名[元素个数] - 方括号中的数字定义了要存放在数组中的元素个数,称为数组维
- 数组有一个类型,它组合了元素的类型和数组中的元素个数
- 存储在数组中的每个数据项都用相同的名称访问,在上述例子中,该名称就是numbers.可以在数组名称后的方括号内使用索引值,索引值是从零开始的连续的整数。0是第一个元素的索引值,注意,索引值是从0开始的,不是1.数组元素的索引值是与第一个元素的偏移量
存在的问题
如何访问数组元素的值?
如何访问数组元素???
(1)要选择某个元素,可以在数组名称后的方括号内使用索引值
(2)在程序执行期间计算的整数表达式。该整数必须是对数组有效的索引值。
5.13 使用数组
- 数组可以由整个数组当作函数的参数,也可以由数组中的某个元素当作函数的参数:
1、整个数组当作函数参数,即把数组名称传入函数中,例如:
2、数组中的元素当作函数参数,即把数组中的参数传入函数中,例如:
数组作为函数参数时注意以下事项:
1、数组名作为函数实参传递时,函数定义处作为接收参数的数组类型形参既可以指定长度也可以不指定长度。
2、数组元素作为函数实参传递时,数组元素类型必须与形参数据类型一致。
5.2 寻址运算符 &
- 寻址运算符&输出其操作数的内存地址,寻址运算符&广泛用于scanf(),寻址运算符放在存储输入的变量名称之前,scanf()函数就可以利用这个变量的地址
把寻址运算符放在变量名称之前,函数就可以利用这个变量的地址。 - 使用%u显示sizeof生成的值
使用新的格式说明符%p来输出变量的地址(内存地址)
5.3 数组名称和地址
long number[4]
数组名称number指定了存储数据项的内存区域地址,把该地址和索引值组合起来就可以找到每一个元素
声明数组时要给编译器提供为数组分配内存所需的所有信息。
- 值的类型决定了每个元素需要的字节数
数组维指定看元素的个数 - 数组占用的字节数是元素个数乘以每个元素的字节数
- 数组元素的地址是数组开始的地址,加上元素的索引值乘以数组中每个元素类型所需的字节
5.4 数组的初始化
- 在大括号中指定一列初值,它们用逗号分开,并且数组大小由列表中的初值个数来确定。
double values[] = { 1.5, 2.5, 3.5, 4.5, 5.5 }
此语句声明了包含5个元素的数组values,values[0]的初值是1.5 - 整个数组初始化为零
double values[5] ={0.0} - 前三个元素用括号内的值初始化,后两个元素初始化为0
double values[5] ={1.5, 2.5, 3.5}
5.5 确定数组的大小
- sizeof 运算符可以计算指定类型的变量所占用的字节数,
printf("The size of a variable of type long is %zu bytes.\n", sizeof(long));
- sizeof运算符后的类型名称的括号是必须的
- 注意:
sizeof运算符生成size_t类型的值 - sizeof运算符用于数组可以
- 数组的声明
double values[5] = {1.5, 2.5, 3.5, 4.5, 5.5 }
- 可以用以下语句输出这个数组所占用的字节数
printf("The size of the array, values , is %zu bytes.\n", sizeof values); - 输出如下:
The size of the array, values, is 40 bytes.
*数组占用的内存是单个元素的字节数乘以元素个数, 使用sizeof运算符计算数组中元素的数目
size_t element_count = sizeof values/sizeof values[0];
- 计算数组元素的数量
size_t element_count = sizeof values/sizeof(double);
- sizeof运算符应用于变量时不需要使用括号,但一般还是使用它们
double values[5] = {1.5, 2.5, 3.5, 4.5 , 5.5}
size_t element_count = sizeof(values)/sizeof(values[10])
printf("The size of the array is %zu bytes ", sizeof(values));
printf("and there are %u elements of %zu bytes each\n", element_count, sizeof(values)[0]));
该语句输出如下:
The size of the arry is 40 bytes and there are 5 elements of 8 bytes each
*在使用循环处理数组
double values[5] = { 1.5, 2.5, 3.5, 4.5, 5.5 };
double sum = 0.0;
for(unsigned int i = 0; i < sizeof(values)/sizeof(values[0]) ; ++i)
sum +=values[i];
printf("The sum of the values is %.2f", sum );
这个循环将数组中所有的元素加起来,使用sizeof运算符计算数组的元素的个数
5.6 多维数组
- 声明二维数组
float carrots[25] [50];
以上语句声明了一个数组carrots,它包含25行50个浮点数元素。注意:每一维都放在自己的方括号中。 - 声明二维浮点数组
float number[3][5]; - 分配给每个元素的内存量取决于数组所含的变量的类型
float number [4] [10]
数组元素类型float.占4 个字节。数组占用的内存总数4410个字节,即160个字节
5.7 多维数组的初始化
多维数组的定义格式是:
数据类型 数组名称[常量表达式1][常量表达式2]...[常量表达式n];
二维数组的初始化
二维数组的初始化类似于一维数组的初始化,区别是把每一行的初始值放在大括号{}中,再把所有行放在一对大括号中:
int number [3] [4] = {
{ 10, 20, 30, 40 },
{ 15, 25, 35 ,45 },
{ 46, 48, 49, 59 }
};
三维数组的初始化
三维数组有三级嵌套的括号;内层的括号包含每行的初始值。
int number [2][3][4] ={
{
{ 10, 20, 30, 40 },
{ 15, 25, 35 ,45 },
{ 46, 48, 49, 59 }
},
{
{ 10, 20, 30, 40 },
{ 15, 25, 35 ,45 },
{ 46, 48, 49, 59 }
}
};
如果提供的初始值个数少于行中的元素数,就必须给每一行的值加上括号。
- 利用嵌套循环处理多维数组中的所有元素,嵌套的层数就是数组的维数
int sum = 0;
for( int i = 0, i < 2; ++i)
{
for(int j = 0, j < 3; ++j)
{
for(int k =0, k <4 ; ++k)
{
sum += number[i][j][k];
}
}
}
printf("The sum of the value in the numbers array is %d.", sum);
- 使用sizeof运算符可以确定多维数组中每一维的元素个数
for(int i = 0, i < sizeof(numbers)/sizeof(numbers[0]) ; ++i)
{
for(int j = 0, j < sizeof(numbers[0])/sizeof(numbers[0][0]) ; ++j)
{
for(int k = 0, k <sizeof(numbers[0][0]/sizeof(numbers[0][0][0]); ++k)
{
sum += numbers[i][j][k];
}
}
}
5.8变长数组
什么是变长数组?
变长数组的作用是什么???是为了达到怎样的目的呢?是实现什么呢??
可以定义其长度在程序运行期间确定的数组
size_t size = 0;
printf("Enter the number of elements you want to store: ");
scanf("%zd", &size);
float values[size];
以上代码,把从键盘上读取的一个值放在size中,使用size的值指定数组的的长度。因为size_t 是用实现代码定义的整数类型,
还可以在执行期间确定二维或多维数组中的任意或所有维。例如:
size_t rows = 0;
size_t columns = 0;
printf("Enter the number of rows you want to store: ");
scanf("%zd",&rows);
printf("Enter the number of columns in a row: ");
scanf("%zd",&columns);
float beans[rows][columns];
#ifdef ___STDC_NO_VLA__
printf("Variable length arrays are not supported.\n");
exit(1);
#endif
以上代码用于检测编译器是否支持变成数组。
这样定义了一个名称为num,数据类型为int的二维数组。其中第一个[3]表示第一维下标的长度,就像购物时分类存放的购物;第二个[3]表示第二维下标的长度,就像每个购物袋中的元素。
我们可以把上面的数组看作一个3×3的矩阵,
如下图:
多维数组的初始化与一维数组的初始化类似也是分两种:
1、数据类型 数组名称[常量表达式1][常量表达式2]...[常量表达式n] = {{值1,..,值n},{值1,..,值n},...,{值1,..,值n}};
2、数据类型 数组名称[常量表达式1][常量表达式2]...[常量表达式n]; 数组名称[下标1][下标2]...[下标n] = 值;
多维数组初始化要注意以下事项:
1、采用第一种始化时数组声明必须指定列的维数。因为系统会根据数组中元素的总个数来分配空间,当知道元素总个数以及列的维数后,会直接计算出行的维数;
2、采用第二种初始化时数组声明必须同时指定行和列的维数
现有三行三列的二维数组int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};,编写程序实现计算对角线元素之和。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
char str[10]={'H','e','l','l','o','\0'}
printf("string length : %\n",strlen(str));
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main (void)
{
char str[] ="hello world";
for(int i=0;i<11;i++)
{
printf("[index:%d]%c\n",i,str[i]);
}
return 0;
}
如何在c语言中创建和使用数组
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int len =10;
int arr[len] ;//这种形式是错的 int arr[10];
for(int a =0;a<len;a++)
{
arr[a] = 0;
}
for(int i =0;i<len;i++)
{
printf("index %d,and value is %d\n",i,arr[i]);
}
return 0;
}
数组的初始化
int arr[] ={1,2,5,7,3,8}
for(int i=0;i<6;i++)
{
printf("%d\n",arr[i]);
}
#include <stdio.h >
#include <stdlib.h >
int main (void)
{
int arr[3][4];
for(int i=0; i<3; i++)
{
for(int j=0; j<4;j++)
{
arr[i][j] =0;
}
}
for(int i=0; i< 3;i++)
{
for( int j =0;i<4;j++)
{
printf("index(%d,%d),%d\n",i,j,arr[i][j]);
}
}
return 0;
}
综合题
在一个长度为10的整型数组里面,保存了班级10个学生的考试成绩。要求编写5个函数,分别实现计算考试的总分,最高分,最低分,平均分和考试成绩降序排序