GESP 客观题评测系统

2025-12-Level-4

2025-12-Level-4

试卷解析总览,可直接查看每题答案与解析。

单选题(每题 2 分)

1 题(单选题

小杨想让指针 p 指向整数变量 x,正确写法是()。

A.
int p = &x;
B.
int *p = x;
C.
int *p = &x;
D.
p = *x;

正确答案C

解析详情

【答案】C

【考点】指针定义与赋值

【解析】 在 C++ 中,指针变量用于存储内存地址。要让指针 p 指向整数变量 x,需要先声明 p 为指针类型 `int *`,并使用取地址符 `&` 获取变量 x 的地址赋给 p。选项 C 完全符合语法要求。

【易错点】 混淆取地址符 `&` 和解引用符 `*` 的作用。

2 题(单选题

小杨写了如下的指针接力程序,程序执行完后变量 a、*p1 和 *p2 的值分别是()。

int a = 5;
int* p1 = &a;
int* p2 = p1;
*p2 = 10;
A.
5 10 10
B.
5 10 15
C.
10 10 10
D.
5 5 10

正确答案C

解析详情

【答案】C

【考点】指针指向与解引用修改

【解析】 1. `p1` 指向 `a`,`p2 = p1` 使 `p2` 也指向 `a`。 2. `*p2 = 10` 通过指针修改了变量 `a` 的值为 10。 3. 由于 `p1` 和 `p2` 均指向 `a`,解引用 `*p1` 和 `*p2` 获取的都是变量 `a` 的当前值 10。因此 a, *p1, *p2 均为 10。

【易错点】 忽略了多个指针指向同一块内存时,通过任一指针修改数据都会影响其他指针的读取结果。

3 题(单选题

小杨用一个二维数组表示棋盘,其中1表示有棋子,0表示没有棋子。他想知道第2行第3列有没有棋子,可采用的代码是:()。

int a[3][4] = {
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 1, 0, 0}
};
A.
cout << a[1, 2] << endl;
B.
cout << a[1][2] << endl;
C.
cout << a(1, 2) << endl;
D.
cout << a{1}{2} << endl;

正确答案B

解析详情

【答案】B

【考点】二维数组索引访问

【解析】 C++ 二维数组下标从 0 开始。第 2 行对应行下标 1,第 3 列对应列下标 2。标准的访问语法为 `数组名[行下标][列下标]`,即 `a[1][2]`。

【易错点】 混淆第几行/列与实际下标的关系(下标 = 序数 - 1)。

4 题(单选题

执行完下面的代码后,*(p + 5)和 arr[1][1] 的值分别是()。

int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int* p = &arr[0][0];
A.
5 6
B.
6 5
C.
5 5
D.
6 6

正确答案D

解析详情

【答案】D

【考点】二维数组内存布局与指针运算

【解析】 二维数组按行优先存放,`arr[3][4]` 每行 4 个元素。`p + 5` 从 `arr[0][0]` 开始偏移 5 个位置:前 4 个跨过第 0 行,第 5 个落到第 1 行第 1 列(即 `arr[1][1]`)。此时对应元素为 6,因此两者值均为 6。

【易错点】 计算指针偏移时,未正确对应二维数组的行宽。

5 题(单选题

执行完下面的代码后,sum 的值是()。

int arr[2][3][2] = {
    {{1,2}, {3,4}, {5,6}},
    {{7,8}, {9,10}, {11,12}}
};
int sum = 0;
for(int i = 0; i < 2; i++)
    for(int j = 0; j < 3; j++)
        for(int k = 0; k < 2; k++)
            if((i+j+k) % 2 == 0)
                sum += arr[i][j][k];
A.
36
B.
39
C.
78
D.
30

正确答案B

解析详情

【答案】B

【考点】多维数组遍历与条件判断

【解析】 累加满足 `(i+j+k)` 为偶数的元素: (0,0,0)→1, (0,1,1)→4, (0,2,0)→5 (1,0,1)→8, (1,1,0)→9, (1,2,1)→12 总和 = 1 + 4 + 5 + 8 + 9 + 12 = 39。

【易错点】 手动模拟下标组合时,漏算或算错 `(i+j+k)` 的奇偶性。

6 题(单选题

执行完下面的代码后,输出是()。

int a = 1;

void test() {
    int a = 2;
    {
        int a = 3;
        a++;
    }
    a++;
    cout << a << " ";
}

int main() {
    test();
    cout << a;
    return 0;
}
A.
3 1
B.
4 1
C.
3 2
D.
4 2

正确答案A

解析详情

【答案】A

【考点】作用域与变量遮蔽

【解析】 1. `test` 函数内部,代码块 `{ int a = 3; a++; }` 修改的是最内层局部变量,块结束即销毁。 2. 块外的 `a++` 修改的是函数级局部变量(初始为 2),变为 3,输出 3。 3. `main` 中输出的是全局变量 `a`,值仍为 1。因此输出为 3 1。

【易错点】 误以为内层代码块的修改会影响外层同名变量。

7 题(单选题

执行完下面的代码后,a、b 和 c 的值分别是()。

void byValue(int x) { x = 100; }
void byRef(int& x) { x = 200; }
void byPointer(int* x) { *x = 300; }

int main() {
    int a = 1, b = 2, c = 3;
    byValue(a);
    byRef(b);
    byPointer(&c);
    return 0;
}
A.
100 200 300
B.
1 2 3
C.
1 200 300
D.
1 2 300

正确答案C

解析详情

【答案】C

【考点】参数传递方式(值、引用、指针)

【解析】 1. `byValue` 是值传递,不影响原变量 a。 2. `byRef` 是引用传递,直接修改原变量 b 为 200。 3. `byPointer` 是指针传递,通过地址修改原变量 c 为 300。故结果为 1 200 300。

【易错点】 分不清值传递(产生副本)和引用/指针传递(操作原件)的区别。

8 题(单选题

运行如下代码会输出()。

struct Point {
    int x, y;
};
struct Rectangle {
    Point topLeft;
    Point bottomRight;
};
int main() {
    Rectangle rect = {{10, 10}, {20, 20}};
    rect.topLeft.x = 5;
    Point* p = &rect.bottomRight;
    p->y = 5;
    cout << rect.topLeft.x + rect.bottomRight.y;
    return 0;
}
A.
10
B.
30
C.
15
D.
20

正确答案A

解析详情

【答案】A

【考点】结构体成员访问与指针修改

【解析】 1. `rect.topLeft.x` 修改为 5。 2. 通过指针 `p` 修改 `rect.bottomRight.y` 为 5。 3. 最终求和 5 + 5 = 10。

【易错点】 嵌套结构体访问时,混淆了成员名或忽略了中间的赋值修改。

9 题(单选题

给定函数 climbStairs(int n) 的定义如下,则 climbStairs(5) 的返回的值是()。

int climbStairs(int n) {
    if(n <= 2) return n;
    int a = 1, b = 2;
    for(int i = 3; i <= n; i++) {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}
A.
5
B.
8
C.
13
D.
10

正确答案B

解析详情

【答案】B

【考点】递推算法(斐波那契数列)

【解析】 典型的爬楼梯问题递推公式:f(n) = f(n-1) + f(n-2)。 f(1)=1, f(2)=2 f(3)=3, f(4)=5, f(5)=8。 函数通过迭代计算得到 8。

【易错点】 迭代更新 `a` 和 `b` 时步数算错。

10 题(单选题

对如下4个扑克牌进行排序,

struct Card {
    int value;
    char suit; // 花色
};

Card cards[4] = {{5, 'A'}, {3, 'B'}, {5, 'C'}, {3, 'D'}};

使用某排序算法按value排序后,结果为:{3,'D'},{3,'B'},{5,'A'},{5,'C'},则这个排序算法是稳定的吗?

A.
稳定,因为相同 value 的元素相对顺序保持不变
B.
不稳定,因为 {3,'D'} 出现在 {3,'B'} 之前
C.
无法判断
D.
稳定,因为结果是有序的

正确答案B

解析详情

【答案】B

【考点】排序算法的稳定性

【解析】 稳定性要求相同键值的元素在排序后保持原有相对顺序。原序列中 {3,'B'} 在 {3,'D'} 之前,排序后变为 {3,'D'} 在 {3,'B'} 之前,相对顺序改变,故不稳定。

【易错点】 误以为只要最终结果有序就是稳定排序。

11 题(单选题

下面的函数 selectTopK() 实现从 n 个学生中选出前 k 名成绩最好的学生颁发奖学金(不需要对所有学生完全排序,只需要找出前 k 名),则横线上应填写()。

struct Student {
    string name;
    int score;
};

void selectTopK(Student students[], int n, int k) {
    for (int i = 0; i < k; i++) {
        int maxIdx = i;
        for (___, ___){ // 在此处填入代码
            if (students[j].score > students[maxIdx].score) {
                maxIdx = j;
            }
        }
    }
    if (maxIdx != i) {
        Student temp = students[i];
        students[i] = students[maxIdx];
        students[maxIdx] = temp;
    }
}
A.
int j = 0; j < n; j++
B.
int j = i + 1; j < n; j++
C.
int j = i; j < n; j++
D.
int j = 1; j <= n; j++

正确答案B

解析详情

【答案】B

【考点】选择排序思想的应用

【解析】 该算法旨在每轮选出剩余部分的最大值。在外层循环第 `i` 轮,需在下标 `[i+1, n-1]` 范围内寻找比 `students[i]` 更大的元素。因此内层循环起点应为 `j = i + 1`。

【易错点】 内层循环范围选择错误,导致重复比较或逻辑失效。

12 题(单选题

某游戏的排行榜系统需要实时更新玩家分数。每次只有一个玩家的分数发生变化,排行榜已经是按分数降序排列的。现在需要将更新后的玩家调整到正确位置。下面的函数 updateRanking() 要实现上述功能,则两处横线上应分别填写()。

struct Player {
    string name;
    int score;
};

// 玩家索引playerIdx的分数刚刚更新,需要调整位置

void updateRanking(Player players[], int size, int playerIdx) {
    Player updatedPlayer = players[playerIdx];

    if (playerIdx > 0 && updatedPlayer.score > players[playerIdx - 1].score) {
        int i = playerIdx;
        while (_____) { // 在此处填入代码
            players[i] = players[i - 1];
            i--;
        }
        players[i] = updatedPlayer;
    }
    else if (playerIdx < size - 1 && updatedPlayer.score < players[playerIdx + 1].score) {
        int i = playerIdx;
        while (_____) { // 在此处填入代码
            players[i] = players[i + 1];
            i++;
        }
        players[i] = updatedPlayer;
    }
}
A.
i > 0 && updatedPlayer.score > players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].score
B.
i < size - 1 && updatedPlayer.score < players[i + 1].score
i > 0 && updatedPlayer.score > players[i - 1].score
C.
i > 0 && updatedPlayer.score < players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].score
D.
i > 0 && updatedPlayer.score < players[i - 1].score
i < size - 1 && updatedPlayer.score > players[i + 1].score

正确答案A

解析详情

【答案】A

【考点】插入排序思想与数组调整

【解析】 排行榜按降序排列: 1. 分数变大需前移:只要 `i>0` 且分数大于前一名,就将前一名后移。 2. 分数变小需后移:只要 `i<size-1` 且分数小于后一名,就将后一名内移。选项 A 符合描述。

【易错点】 在降序排列的逻辑下,混淆了大于和小于符号的移动方向。

13 题(单选题

给定如下算法,其时间复杂度为()。

bool f(int arr[], int n, int target) {
    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 0; j < n; j++) {
            if (i & (1 << j)) {
                sum += arr[j];
            }
        }
        if (sum == target) return true;
    }
    return false;
}
A.
O(n)O(n)
B.
O(n2)O\left(n^{2}\right)
C.
O(n3)O\left(n^{3}\right)
D.
O(2n)O\left(2^{n}\right)

正确答案B

解析详情

【答案】B

【考点】时间复杂度分析

【解析】 外层循环执行 n 次,内层循环执行 n 次。两层嵌套循环的总执行次数为 n \times n = n^2。尽管内部有位运算,但都是常数时间操作。因此复杂度为 O(n^2)。

【易错点】 看到位运算 `1 << j` 惯性思维误选指数级复杂度,忽略了外层循环界限只是 n。

14 题(单选题

执行下面 C++ 程序,会输出()。

int main() {
    ofstream fout("test.txt");
    fout << "Happy" << endl;
    fout << "New Year";
    fout.close();

    ifstream fin("test.txt");
    string s1, s2;
    fin >> s1;
    getline(fin, s2);
    fin.close();

    cout << s1 << "||" << s2;
    return 0;
}
A.
Happy|| New Year
B.
Happy| New Year
C.
HappyNew Year|
D.
Happy|

正确答案D

解析详情

【答案】D

【考点】文件流输入与 `getline` 特性

【解析】 1. `fin >> s1` 读取第一个单词 "Happy",停在换行符前。 2. `getline(fin, s2)` 读取当前位置到行尾的所有内容。由于当前紧邻换行符,它读入空字符串并消耗换行符。因此 `s2` 为空,输出 `Happy||`。

【易错点】 误以为 `fin >> s1` 会消耗掉行尾的换行符,或者误以为 `getline` 会自动跳转到有内容的一行。

15 题(单选题

执行下面 C++ 代码,会输出()。

int divide(int a, int b) {
    if(b == 0) throw "Division by zero";
    return a / b;
}

int main() {
    int result = 0;
    try {
        result = divide(10, 0);
        cout << "A";
    }
    catch(const char* msg) {
        cout << "B";
        result = -1;
    }
    cout << result;
    return 0;
}
A.
A0
B.
B-1
C.
A10
D.
程序崩溃

正确答案B

解析详情

【答案】B

【考点】异常处理机制(try-catch)

【解析】 1. `divide(10, 0)` 抛出异常,`try` 块内后续语句 `cout << "A"` 被跳过。 2. 进入 `catch` 块输出 `B` 并设 `result = -1`。 3. 执行 `try-catch` 外的 `cout << result` 输出 -1。综合输出 B-1。

【易错点】 误认为抛出异常后 catch 块外的代码不再执行。

判断题(每题 2 分)

1 题(判断题

小杨正在调试他的温度传感器程序,其中变量 x 保存当前温度。下面这段代码运行后,变量 x 的值变成了 8。

int x = 5;
int *p = &x;
*p = *p + 3;

正确答案正确

解析详情

【答案】正确

【考点】指针解引用赋值

【解析】 `*p` 即为变量 `x` 的别名。`*p = *p + 3` 相当于 `x = 5 + 3`,故 `x` 变为 8。

【易错点】 无。

2 题(判断题

一个结构体不能包含另一个结构体。

正确答案错误

解析详情

【答案】错误

【考点】结构体嵌套定义

【解析】 C++ 允许结构体成员是另一个已定义的结构体类型(嵌套结构体)。

【易错点】 误以为结构体只能包含基本数据类型。

3 题(判断题

在 C++ 中,定义如下二维数组: int a[3][4];,数组 a 在内存中是按行优先连续存放的,即 a[0][0]、a[0][1]、a[0][2]、a[0][3] 在内存中是连续的。

正确答案正确

解析详情

【答案】正确

【考点】二维数组内存布局

【解析】 C++ 二维数组采用行优先存储,即同一行的元素在内存地址上是连续相邻的。

【易错点】 混淆行优先和列优先存储。

4 题(判断题

执行下面程序后,变量 a 的值会变成 15。

void add(int &x){
    x += 10;
}
int a = 5;
add(a);

正确答案正确

解析详情

【答案】正确

【考点】引用传递

【解析】 函数形参是引用类型 `int &x`,修改 `x` 相当于直接操作实参 `a`,故 `a` 变为 15。

【易错点】 误将其当作普通值传递(副本操作)。

5 题(判断题

执行下面的C++代码,会输出8,因为两个指针地址相差8个字节(假设int占4字节)。

int arr[5] = {1, 2, 3, 4, 5};
int* p1 = arr;
int* p2 = arr + 2;

cout << p2 - p1; // 输出结果

正确答案错误

解析详情

【答案】错误

【考点】指针算术运算

【解析】 两个同类型指针相减的结果是它们之间相隔的元素个数,而非字节数。`p2 - p1` 结果为 2。

【易错点】 混淆逻辑单位(元素个数)与物理单位(字节数)。

6 题(判断题

考虑用如下递推方式计算斐波那契数列,时间复杂度是O(n)O(n)

int n = 10;
int f[20];
f[0] = 0;
f[1] = 1;
for (int i = 2; i <= n; i++)
f[i] = f[i - 1] + f[i - 2];

正确答案正确

解析详情

【答案】正确

【考点】算法复杂度分析

【解析】 该代码通过单一循环完成计算,执行次数与 n 成正比,复杂度为 O(n)。

【易错点】 混淆递推版(O(n))和递归版(指数级)斐波那契的时间复杂度。

7 题(判断题

冒泡排序和插入排序都是稳定排序算法。

正确答案正确

解析详情

【答案】正确

【考点】排序算法稳定性性质

【解析】 冒泡和插入排序在比较相等元素时均可设计为不改变相对位置,故属于稳定排序。

【易错点】 将选择排序(不稳定)误认为是稳定排序。

8 题(判断题

下面这段代码实现了选择排序算法。

void sort(int a[], int n) {
    for (int i = 1; i < n; i++) {
        int x = a[i];
        int j = i - 1;
        while (j >= 0 && a[j] > x) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = x;
    }
}

正确答案错误

解析详情

【答案】错误

【考点】排序算法识别

【解析】 代码逻辑是通过寻找位置插入当前元素,这是典型的插入排序实现,而非选择排序。

【易错点】 分不清插入排序(移动插入)和选择排序(找最值交换)的代码特征。

9 题(判断题

下面代码可以正常编译并输出 10。

#include <iostream>
using namespace std;

int calculate(int x, int y = 10);
int main() {
    cout << calculate(5); // 调用1
    return 0;
}

int calculate(int x, int y) {
    return x * y;
}

int calculate(int x) { // 重载函数
    return x * 2;
}

正确答案错误

解析详情

【答案】错误

【考点】函数重载冲突与调用歧义

【解析】 `calculate(5)` 既能匹配带默认参数的版本,也能匹配单参数版本,编译器无法确定调用哪个,产生歧义报错。

【易错点】 忽略了默认参数导致重载函数调用时的二义性。

10 题(判断题

执行下面代码会输出 100 。

int main() {
    ofstream fout("data.txt");
    fout << 10 << " " << 20 << endl;
    fout << 30 << " " << 40;
    fout.close();

    ifstream fin("data.txt");
    int a, b, c, d;
    fin >> a >> b >> c >> d;
    fin.close();

    cout << a + b + c + d;
    return 0;
}

正确答案正确

解析详情

【答案】正确

【考点】文件读写操作

【解析】 抽取运算符 `>>` 会自动跳过空格和换行符。四个整数被依次读入,总和为 100。

【易错点】 误以为换行符会阻止 `>>` 继续读取后续整数。