国庆练习(Day24)-作业一

时间:2024-10-08 15:56:08

数组练习

  1. 选择题

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'。

解答:

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;
}