引言
现程序要求,录入班里60名同学的所有成绩,我们应该怎么录入呢?按照我们之前所学习的难道要声明60个变量来录入成绩嘛?
就像:
int main() {
int a1,a2,a3,...,a60;
scanf("%d%d%d...%d",&a1,&a2,&a3,...,&a60);
printf("Hello, World!\n");
return 0;
}
注:上述代码中出现的"…"仅代表a3到a60之间的变量,在实际代码中并不能这样使用。
这样进行录入数据会使得变量冗余繁多。接下来我们引入数组,利用数组录入同类数据。
一、一维数组
1.1 数组的一般形式
数组是一组有序数据的集合。并且数组的每一个元素都属于同一个数据类型。
一维数组的一般形式为:
类型说明符 数组名[常量表达式];
如:
int a[60];
1.2 声明数组时需要注意的规则
声明数组时要遵守以下规则:
1、数组名的命名规则和变量名相同,遵循标识符命名规则
2、在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
就如:
int a[60];
就表示数组a有60个元素,需要注意的是数组下标是从0开始的。即数组a的元素是从a[0],a[1],a[2],…,a[59]。而不存在a[60]如果我们引用了a[60]就会出现数组越界的错误。
3、常量表达式中可以包括常量和符号常量,但是不能包含变量。
如:
int n;
scanf("%d",&n);
int a[n];
上述代码打算动态录入数组a的数组长度,是不可取的。
1.3 一维数组的引用
引用数组元素的表示形式为
数组名[下标]
如:
int a[10];
int m;
m = a[2];
需要注意的是a[10]和a[2]在这里的区别
a[10]前面是类型说明符int,说明是定义
a[2]前面是赋值符号,说明这里是对数组元素的引用
1.4 一维数组的初始化
我们可以在定义数组时直接进行初始化
如:
int a[10] = {0,1,2,3,4,5,6,7,8,9};
我们可以使用循环遍历数组
int main() {
int a[10] = {0,1,2,3,4,5,6,7,8,9};
for(int i = 0;i < 10;i++) {
printf("%d\n",a[i]);
}
return 0;
}
运行结果如下:
我们也可以给一部分元素赋值
如:
int main() {
int a[10] ={1,2,3,4,5};
for(int i = 0;i < 10;i++) {
printf("%d\n",a[i]);
}
return 0;
}
运行结果:
我们可以看到未赋值的元素均为0。
二、二维数组
二维数组是一种矩阵结构,由多个一维数组通过行和列组合而成,常用于存储和处理相关数据。
2.1 二维数组的定义
二维数组的一般形式为:
类型说明符 数组名[常量表达式][常量表达式];
例如:
int a[3][4];
二维数组可以看成一个特殊的一维数组。
如果把a[0]看成一个一维数组,它的元素:a[0],a[1],a[2]
每个元素又是包含了四个元素的一维数组
a[0] ---------a[0][0] , a[0][1] , a[0][2] , a[0][3]
a[1] ---------a[1][0] , a[1][1] , a[1][2] , a[1][3]
a[2] ---------a[2][0] , a[2][1] , a[2][2] , a[2][3]
可以用简单的三行四列矩阵来理解
需要注意的是:我们使用矩阵形式(如上述的数组a三行四列矩阵)表示二维数组是逻辑上的概念。而在内存中,各元素是连续存放的,不是二维的,是线性的。
2.2 二维数组的引用
二维数组元素的表达形式为:
数组名[下标][下标]
下标值的范围应该一一对应
如上面所提到的a[3][4]
数组a的行下标(即第一个下标)对应的范围就是0~2
数组a的列下标(即第二个下标)对应的范围就是0~3
2.3 二维数组的初始化
我们可以根据一维数组的形式对二维数组进行初始化
如:
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
我们同样可以使用循环讲二维数组的元素输出
int main() {
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
for(int i = 0;i < 3;i++) {
for(int j = 0;j < 4;j++) {
printf("%d\t",a[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
我们也可以把所有的元素都放在一个花括号里面
如:
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
这样更能体现出二维数组线性存储。
三、字符数组
C语言中没有字符串类型,也没有字符串变量(像在Java中的String类型),在C语言中字符串是存放在字符型数组中的。
字符数组的定义与一维数组的定义类似
例如:
char c[10];
需要注意的是:
C语言的字符数组在遇到’\0’(即空字符)时,表示字符串结束,把他前面的字符组成一个字符串。
例如:录入一个字符串,并输出:
int main() {
char c[5];
scanf("%s",c);
printf(c);
return 0;
}
运行结果:
当输入的字符串没有’\0’时
当输入的字符串有’\0’时
四、数组越界问题
通过上面对数组的介绍,我们了解到,我们是通过数组的下标来获取数组元素,但是当我们使用了该数组没有的下标会发生什么呢?
如:
int main() {
int a[5] = {1,2,3,4,5};
printf("The Value Of a[6] Is %d", a[6]);
return 0;
}
运行结果:
在上述例子中,我们声明了一个包含五个整数元素的整型数组a,并将前五个位置分别赋值为1, 2, 3, 4, 5。然后,我们试图打印第六个位置a[6],但实际上数组只有五个元素,因此获取的值未定义(由于内存的内容随机)并且程序可能会抛出一个异常或者输出错误信息,并以非正常方式退出。
C语言数组越界指尝试访问数组中不存在的元素或超出数组的索引范围。这通常会导致程序的不稳定性和未定义行为,包括崩溃、内存损坏、数据损坏等问题。