GESP 客观题评测系统
2025-12-Level-4
2025-12-Level-4
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题)
小杨想让指针 p 指向整数变量 x,正确写法是()。
int p = &x;int *p = x;int *p = &x;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;正确答案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}
};正确答案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];正确答案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];
正确答案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
解析详情
【答案】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;
}正确答案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
解析详情
【答案】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;
}正确答案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'},则这个排序算法是稳定的吗?
正确答案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;
}
}正确答案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;
}
}i > 0 && updatedPlayer.score > players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].scorei < size - 1 && updatedPlayer.score < players[i + 1].score
i > 0 && updatedPlayer.score > players[i - 1].scorei > 0 && updatedPlayer.score < players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].scorei > 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;
}正确答案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;
}正确答案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;
}正确答案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 题(判断题)
考虑用如下递推方式计算斐波那契数列,时间复杂度是。
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。
【易错点】 误以为换行符会阻止 `>>` 继续读取后续整数。