数组练习
-
选择题
1.1、若有定义语句:int a[3][6]; ,按在内存中的存放顺序,a 数组的第10个元素是
a[0][4] B) a[1][3] C)a[0][3] D)a[1][4]
解析:
从 a[0][0] 开始,第一行有 6 个元素,分别是 a[0][0] 到 a[0][5],即第 1 到第 6 个元素。
接着从 a[1][0] 开始,第二行前 4 个元素是 a[1][0] 到 a[1][3],即第 7 到第 10 个元素。
所以,第 10 个元素是 a[1][3]
解答:
B
1.2、有数组 int a[5] = {10,20,30,40,50}, 以下表达式编译错误是____________。
A) a ++ ;
B) a[5] = 20 ;
C) a + 20 ;
D) (a-3, a[3]) ;
解析:
A) a++ ;
错误:a++ 是不合法的。
原因:在 C 语言中,数组名 a 是一个指向数组第一个元素的指针常量,它的值不可改变。也就是说,数组名 a 不能被自增,因为它是一个 常量指针,指向数组首地址,不能通过 ++ 操作改变。
B) a[5] = 20 ;
错误:虽然语法上没有问题,但会导致 数组越界 错误。
原因:a[5] 实际上是访问数组的第 6 个元素,而 a[5] 数组只有 5 个元素,索引范围是 a[0] 到 a[4]。因此,访问 a[5] 会导致 越界访问,尽管某些编译器可能不会报错,但这是一个逻辑错误。
C) a + 20 ;
正确:这个表达式不会编译错误。
原因:a + 20 是一个合法的指针运算。它将指针 a 偏移 20 个元素的位置,虽然这样做的结果可能是非法的地址访问,但仅仅是表达式本身不会导致编译错误。
D) (a-3, a[3]) ;
正确:这个表达式不会编译错误。
原因:这是一个逗号表达式,先计算 a-3(虽然结果无实际意义),然后计算 a[3],最终返回 a[3] 的值。语法上没有问题。
解答:
A
1.3、以下错误的定义语句是 _______
A)int x[][3] = {{0},{1},{1,2,3}};
B)int x[4][3] = {{1,2,3},{1,2,3},{1,2,3},{1,2,3}};
C)int x[4][] = {{1,2,3},{1,2,3},{1,2,3},{1,2,3}};
D)int x[][3] = {1,2,3,4};
解析:
A) int x[][3] = {{0}, {1}, {1, 2, 3}};
正确:这是合法的定义。
原因:二维数组在定义时,必须指定列的大小(本例中的 [3])。行数可以省略,编译器会根据初始化的内容推断行数。每行的元素少于 3 时,未指定的元素会自动填充为 0。因此,这个定义是合法的。
B) int x[4][3] = {{1,2,3},{1,2,3},{1,2,3},{1,2,3}};
正确:这是合法的定义。
原因:明确定义了 4 行 3 列的二维数组,并且每行都初始化了 3 个元素,符合数组初始化规则。
C) int x[4][] = {{1,2,3},{1,2,3},{1,2,3},{1,2,3}};
错误:这是非法的定义。
原因:在声明二维数组时,列的大小必须明确指定,但这个语句没有为列指定大小(即 [] 是空的)。编译器无法推断每行有多少个元素,因此会报错。
D) int x[][3] = {1, 2, 3, 4};
正确:这是合法的定义。
原因:这是二维数组的另一种初始化方式。虽然看起来像是一维数组的初始化,但编译器会将 1, 2, 3, 4 填充到 [3] 列的二维数组中。结果是 x[0][0] = 1, x[0][1] = 2, x[0][2] = 3, x[1][0] = 4,其余的未初始化元素将被自动填充为 0。因此,这个定义也是合法的。
解答:
C
1.4、设int i,x[3][3]={1,2,3,4,5,6,7,8,9};则下面语句
for(i=0;i<3;i++)
printf(″%d, ″,x[i][2-i]);
的输出结果是
A)1, 4, 7 B)1, 5, 9 C)3, 6, 9 D)3, 5, 7
解析:
这里 x[i][2-i] 表示:
当 i = 0 时,x[0][2-0] = x[0][2] = 3
当 i = 1 时,x[1][2-1] = x[1][1] = 5
当 i = 2 时,x[2][2-2] = x[2][0] = 7
解答:
D
1.5、表达式“sizeof(int [1][2])/sizeof(int)”的值为_____。
A) 2 B) 3 C) 4 D) 5
解析:
sizeof(int [1][2]):
这个数组包含 1 行 2 列,总共有 1 × 2 = 2 个 int 元素。
每个 int 占 4 字节,因此整个数组的大小为 2 × 4 = 8 字节。
sizeof(int):
这是单个 int 类型的大小,在大多数系统上为 4 字节。
解答:
A
1.6有以下程序
#include main()
{ char s[]="012xy\07s34f4w2";
int i,n=0;
for(i=0;s[i]!=0;i++)
if(s[i]>='0'&&s[i]<='9')
n++;
printf("%d\n",n);
}
程序运行后的输出结果是____________
A)0 B)3 C)7 D)8
解析:
字符数组 s[] 的内容为 "012xy\07s34f4w2":
"012xy\07s34f4w2" 是一个字符串常量。
\07 是一个八进制转义字符,对应的值是 7。
这个字符串的实际内容是:"012xy\x07s34f4w2",它的长度是 14 个字符(包括 \07)。
但在这个程序中,八进制字符不会影响字符串的解析,它仅仅是作为一个不可见的字符。
for 循环 遍历整个字符串,直到遇到空字符 '\0' 为止。
在 if (s[i] >= '0' && s[i] <= '9') 中,检查当前字符是否为数字字符 '0' 到 '9'。如果是数字字符,则计数器 n 增加。
字符串 "012xy\07s34f4w2" 中的数字字符为:
'0', '1', '2', '3', '4', '4', '2'
一共 7 个数字字符。
解答:
C
1.7、有以下程序
#include <stdio.h>
main( )
{ char s[ ]=”wstuv”; printf(“%c\n”,*s+2);
}
程序运行后的输出结果是
A)t B) tuv C)y D)出错
解析:
s 是一个字符数组,数组名 s 是指向第一个元素的指针。
*s 解引用 s,表示数组的第一个元素 s[0],即字符 'w'。
表达式 *s + 2:
*s 取的是 s[0],即字符 'w'。
'w' 在 ASCII 码中的值是 119。
*s + 2 相当于 119 + 2 = 121,ASCII 码值 121 对应的字符是 'y'。
printf("%c\n", *s + 2); 输出的就是字符 'y'。
解答:
C
1.8 数组 int a[5] = {10, 20, 30, 40,50}, 有以下语句,其输出_______
printf(“%d\n”, *(&a +1) );
A) 20 B) 30 C) 随机值 D)编译报错
解析:
&a 的含义:
&a 是 数组 a 的地址,它的类型是 int (*)[5],即指向一个大小为 5 的整型数组的指针。
注意,这与 a 的地址(指向数组第一个元素 a[0] 的地址)是不同的。a 作为数组名时相当于 &a[0],是一个指向第一个元素的指针,而 &a 是整个数组的地址。
&a + 1 的含义:
&a + 1:这个表达式实际上是将 &a (数组 a 的地址)偏移一个数组的大小。因为 &a 是一个指向整个数组的指针,偏移 1 意味着它指向了数组 a 之后的地址。
也就是说,&a + 1 实际上指向的是数组 a[5] 后面的内存位置。
*( &a + 1 ) 的含义:
*( &a + 1 ) 试图 解引用 偏移后的地址。由于 &a + 1 指向数组 a 之外的内存,这意味着该表达式取出的值是数组 a 之后的内存中的内容。
这里访问的是超出数组范围的内存空间,会导致未定义行为。因此,输出的值是 随机的,也就是不可预测的。
解答:
C
1.9 有以下程序
# include <stdio.h>
int main()
{ int s[12]={1,2,3,4,4,3,2,1,1,1,2,3}, c[5]={0,0,0,0,0}, i ;
for(i=0;i<12;i++) c[s[i]]++ ;
for(i=1;i<5;i++) printf(“%d,”,c[i]); printf(“\n”);
}
A) 4 ,3, 3, 2 B) 2 , 3, 4, 4
C) 1, 2, 3 ,4 D ) 4, 4, 2 ,3
解析:
数组 s[12] 的初始化为:{1, 2, 3, 4, 4, 3, 2, 1, 1, 1, 2, 3}。
这个数组包含 12 个元素。
数组 c[5] 的初始化为:{0, 0, 0, 0, 0}。
这是一个用于统计出现次数的数组,c[i] 表示整数 i 在数组 s 中出现的次数。
for 循环统计元素出现次数:
c[s[i]]++ 根据数组 s[i] 的值,更新数组 c[] 的对应索引。
这意味着,数组 c 会记录数组 s 中数字 1 到 4 的出现次数。
数组 s 中每个数字的出现次数:
数字 1 出现了 4 次。
数字 2 出现了 3 次。
数字 3 出现了 3 次。
数字 4 出现了 2 次。
因此,数组 c 更新为:{0, 4, 3, 3, 2}。
输出部分:
for (i = 1; i < 5; i++) printf("%d,", c[i]);
该循环会打印数组 c[1] 到 c[4] 的值,也就是 4, 3, 3, 2。
解答:
A
1.10 有数组 int a[3][4] = {10,20,30,40,50,60,70,80,90,100,110,120},执行以下语句输出的是_______________
printf(“%d\n”, *(*a+2) + 3 );
A) 语句有错 B) 120 C) 30 D) 33
解析:
*a:
a 是一个二维数组,*a 代表 指向第一行的指针,也就是 a[0],即地址 &a[0][0],指向的是第一个元素 10。
*a + 2:
*a 是 a[0] 的首地址,即 &a[0][0],加上 2 就是指向 a[0][2],也就是 30 的地址。
*(*a + 2):
这是对 a[0][2] 解引用,结果是 30。
*(*a + 2) + 3:
这一步是在 30 的基础上再加上 3,所以结果是 30 + 3 = 33
解答:
D
2、填空题
2.1、有以下程序
#include <stdio.h>
main( )
{ int i,n[ ]={0,0,0,0,0};
for(i=1;i<=4;i++)
{n[i]=n[i-1]*3+1;
printf(“%d”,n[i]);}
}
程序运行后输出结果是 __________
解析:
当 i = 1:
n[1] = n[0] * 3 + 1 = 0 * 3 + 1 = 1
输出:1
当 i = 2:
n[2] = n[1] * 3 + 1 = 1 * 3 + 1 = 4
输出:4
当 i = 3:
n[3] = n[2] * 3 + 1 = 4 * 3 + 1 = 13
输出:13
当 i = 4:
n[4] = n[3] * 3 + 1 = 13 * 3 + 1 = 40
输出:40
解答:
141340
2.2、执行以下程序的输出结果是_ .
#include <stdio.h>
int main()
{ int i,n[4]={1,0,0,0};
for(i=1;i<=3;i++)
{ n[i]=n[i-1]*2+1; printf("%d",n[i]); }
}
解析:
当 i = 1:
n[1] = n[0] * 2 + 1 = 1 * 2 + 1 = 3
输出:3
当 i = 2:
n[2] = n[1] * 2 + 1 = 3 * 2 + 1 = 7
输出:7
当 i = 3:
n[3] = n[2] * 2 + 1 = 7 * 2 + 1 = 15
输出:15
解答:
3715
2.3、下面程序运行的结果为_________。
main()
{
int x[5],i;
x[0] = 1;x[1] = 2;
for(i = 2;i<5;i++) x[i] = x[i-1] + x[i-2];
for(i = 2;i<5;i++) printf(“%d”,x[i]);
}
解析:
i = 2:
x[2] = x[1] + x[0] = 2 + 1 = 3
当 i = 3:
x[3] = x[2] + x[1] = 3 + 2 = 5
当 i = 4:
x[4] = x[3] + x[2] = 5 + 3 = 8
数组 x 的最终内容:
x[0] = 1
x[1] = 2
x[2] = 3
x[3] = 5
x[4] = 8
第二 for 循环:
再次循环从 i = 2 到 i < 5,输出 x[2], x[3], x[4] 的值。
输出:3, 5, 8
解答:
358
2.4、有以下程序
#include <sthio.h>
int main()
{
int arr[] = {1,3,5,7,2,4,6,8}, i, start ;
scanf(“%d”, &start);
for(i=0,i<7,i+=2)
printf(“%d”,arr[(start+i)%5]);
}
若在程序运行时输入整数 10 <回车>,则输出结果为_______
解析:
当 i = 0:
arr[(start + i) % 5] = arr[(10 + 0) % 5] = arr[10 % 5] = arr[0]
输出:1
当 i = 2:
arr[(start + i) % 5] = arr[(10 + 2) % 5] = arr[12 % 5] = arr[2]
输出:5
当 i = 4:
arr[(start + i) % 5] = arr[(10 + 4) % 5] = arr[14 % 5] = arr[4]
输出:2
当 i = 6:
arr[(start + i) % 5] = arr[(10 + 6) % 5] = arr[16 % 5] = arr[1]
输出:3
解答:
1523
2.5下面程序运行的结果为_________。
#include "stdio.h"
main()
{ int i,j,a[]={0,2,8,4,5};
printf("\n");
for(i=1;i<=5;i++)
{ j=5-i;
printf("%2d",a[j]);
}
}
解析:
当 i = 1:
j = 5 - 1 = 4
输出 a[4] = 5。
当 i = 2:
j = 5 - 2 = 3
输出 a[3] = 4。
当 i = 3:
j = 5 - 3 = 2
输出 a[2] = 8。
当 i = 4:
j = 5 - 4 = 1
输出 a[1] = 2。
当 i = 5:
j = 5 - 5 = 0
输出 a[0] = 0。
解答:
5 4 8 2 0
2.6有以下程序
#include <stdio.h>
int main()
{ int n[2],i,j;
for(i=0;i<2;i++) n[i]=0; for(i=0;i<2;i++)
for(j=0;j<2;j++) n[j]=n[i]+1;
printf(“%d\n”,n[1]);
}
程序运行后的输出结果是 【】
解析:
第一次for循环作用是对数组进行初始化全部赋值为0
第二个双层for循环外层是控制次数
第一次i=0时
j=0
n[0]=n[0]+1=0+1=1
j=1
n[1]=n[0]+1=1+1=2
第二次i=1时
j=0
n[0]=n[1]+1=2+1=3
j=1
n[1]=n[1]+1=2+1=3
输出n[1]为3
解答:
3
3、编程题
3.1、 一个班10个学生的成绩,存放在一个一维数组中,要求找出其中成绩最高的学生的成绩和该生的序号。试编程。(试着用下标法和地址法两种方法表示数组)
代码解答:
下标法:
#include <stdio.h>
int main() {
int scores[10] = {85, 92, 78, 90, 88, 95, 82, 80, 91, 89}; // 假设的成绩
int maxScore = scores[0]; // 假设第一个学生成绩为最高分
int maxIndex = 0; // 最高分的序号(下标)
// 找到最高分和对应的序号
for (int i = 1; i < 10; i++) {
if (scores[i] > maxScore) {
maxScore = scores[i]; // 更新最高分
maxIndex = i; // 更新最高分序号
}
}
// 输出结果
printf("最高成绩: %d\n", maxScore);
printf("该生的序号: %d\n", maxIndex + 1); // 序号从 1 开始
return 0;
}
地址法:
#include <stdio.h>
int main() {
int scores[10] = {85, 92, 78, 90, 88, 95, 82, 80, 91, 89}; // 假设的成绩
int maxScore = *scores; // 假设第一个学生成绩为最高分
int maxIndex = 0; // 最高分的序号(下标)
// 找到最高分和对应的序号
for (int i = 1; i < 10; i++) {
if (*(scores + i) > maxScore) {
maxScore = *(scores + i); // 更新最高分
maxIndex = i; // 更新最高分序号
}
}
// 输出结果
printf("最高成绩: %d\n", maxScore);
printf("该生的序号: %d\n", maxIndex + 1); // 序号从 1 开始
return 0;
}
3.2、有5个学生上4门课程,要求输入全部学生的各门课程成绩,然后输出各门课程的平均成绩,并按照各个学生的平均成绩排序(成绩最高的学生排在数组最前面,最低学生排在数组最后面的行) (试着用下标法和地址法两种方法表示数组)。
代码解答:
下标法:
#include <stdio.h>
#define STUDENTS 5
#define SUBJECTS 4
int main() {
int scores[STUDENTS][SUBJECTS]; // 存储学生成绩
float avgScores[STUDENTS]; // 存储每个学生的平均成绩
float subjectAverages[SUBJECTS] = {0}; // 存储每门课程的平均成绩
// 输入学生的成绩
for (int i = 0; i < STUDENTS; i++) {
printf("输入第 %d 个学生的4门课程成绩:\n", i + 1);
for (int j = 0; j < SUBJECTS; j++) {
printf("课程 %d: ", j + 1);
scanf("%d", &scores[i][j]);
}
}
// 计算每个学生的平均成绩
for (int i = 0; i < STUDENTS; i++) {
float total = 0;
for (int j = 0; j < SUBJECTS; j++) {
total += scores[i][j];
}
avgScores[i] = total / SUBJECTS;
}
// 计算每门课程的平均成绩
for (int j = 0; j < SUBJECTS; j++) {
float total = 0;
for (int i = 0; i < STUDENTS; i++) {
total += scores[i][j];
}
subjectAverages[j] = total / STUDENTS;
}
// 按照学生的平均成绩排序(简单选择排序)
for (int i = 0; i < STUDENTS - 1; i++) {
for (int j = i + 1; j < STUDENTS; j++) {
if (avgScores[i] < avgScores[j]) {
// 交换平均成绩
float temp = avgScores[i];
avgScores[i] = avgScores[j];
avgScores[j] = temp;
// 同时交换对应的成绩
for (int k = 0; k < SUBJECTS; k++) {
int tempScore = scores[i][k];
scores[i][k] = scores[j][k];
scores[j][k] = tempScore;
}
}
}
}
// 输出每门课程的平均成绩
printf("\n各门课程的平均成绩:\n");
for (int j = 0; j < SUBJECTS; j++) {
printf("课程 %d: %.2f\n", j + 1, subjectAverages[j]);
}
// 输出每个学生的成绩和平均成绩
printf("\n学生的成绩及平均成绩:\n");
for (int i = 0; i < STUDENTS; i++) {
printf("第 %d 个学生成绩: ", i + 1);
for (int j = 0; j < SUBJECTS; j++) {
printf("%d ", scores[i][j]);
}
printf(" | 平均成绩: %.2f\n", avgScores[i]);
}
return 0;
}
地址法:
#include <stdio.h>
#define STUDENTS 5
#define SUBJECTS 4
int main() {
int scores[STUDENTS][SUBJECTS]; // 存储学生成绩
float avgScores[STUDENTS]; // 存储每个学生的平均成绩
float subjectAverages[SUBJECTS] = {0}; // 存储每门课程的平均成绩
// 输入学生的成绩
for (int i = 0; i < STUDENTS; i++) {
printf("输入第 %d 个学生的4门课程成绩:\n", i + 1);
for (int j = 0; j < SUBJECTS; j++) {
printf("课程 %d: ", j + 1);
scanf("%d", (*(scores + i) + j)); // 地址法输入
}
}
// 计算每个学生的平均成绩
for (int i = 0; i < STUDENTS; i++) {
float total = 0;
for (int j = 0; j < SUBJECTS; j++) {
total += *(*(scores + i) + j); // 地址法计算
}
avgScores[i] = total / SUBJECTS;
}
// 计算每门课程的平均成绩
for (int j = 0; j < SUBJECTS; j++) {
float total = 0;
for (int i = 0; i < STUDENTS; i++) {
total += *(*(scores + i) + j); // 地址法计算
}
subjectAverages[j] = total / STUDENTS;
}
// 按照学生的平均成绩排序(简单选择排序)
for (int i = 0; i < STUDENTS - 1; i++) {
for (int j = i + 1; j < STUDENTS; j++) {
if (avgScores[i] < avgScores[j]) {
// 交换平均成绩
float temp = avgScores[i];
avgScores[i] = avgScores[j];
avgScores[j] = temp;
// 同时交换对应的成绩
for (int k = 0; k < SUBJECTS; k++) {
int tempScore = *(*(scores + i) + k);
*(*(scores + i) + k) = *(*(scores + j) + k);
*(*(scores + j) + k) = tempScore;
}
}
}
}
// 输出每门课程的平均成绩
printf("\n各门课程的平均成绩:\n");
for (int j = 0; j < SUBJECTS; j++) {
printf("课程 %d: %.2f\n", j + 1, subjectAverages[j]);
}
// 输出每个学生的成绩和平均成绩
printf("\n学生的成绩及平均成绩:\n");
for (int i = 0; i < STUDENTS; i++) {
printf("第 %d 个学生成绩: ", i + 1);
for (int j = 0; j < SUBJECTS; j++) {
printf("%d ", *(*(scores + i) + j)); // 地址法输出
}
printf(" | 平均成绩: %.2f\n", avgScores[i]);
}
return 0;
}