文章

【GESP】C++ 2025年3月三级考试-客观题真题解析

不知道为什么,官方只提供了2023年考试客观题的真题解析,从2024年开始,客观题只有答案没有解析。因为孩子正在准备三级考试,因此我将从25年3月的三级题目开始,逐步整理客观题的解析。


一、单选题(每题2分,共30分)

第1题

题目:Base64编码将每3字节的输入数据编码为4字节的输出数据。如果输入数据长度不是3的倍数,会用=号填充。在Base64编码中,如果输入字符串的长度为10字节,编码后的字符串长度是多少( )

  • A. 12字节
  • B. 13字节
  • C. 14字节
  • D. 16字节

答案:D

解析

Base64编码规则是每3个字节编码为4个字节。对于10字节的输入:

  • 10 ÷ 3 = 3组余1字节
  • 编码后的长度 = ceil(10 / 3) × 4 = 4 × 4 = 16字节
  • 由于有余数1字节,需要用2个=填充,但总长度仍为16字节(4组×4字节)

第2题

题目:以下哪个字节序列是合法的UTF-8编码( )

  • A. 0xC0 0x80
  • B. 0xF0 0x90 0x80 0x80
  • C. 0x80 0x80 0x80
  • D. 0xFF 0xFE 0xFD

答案:B

解析

UTF-8编码规则:

  • 4字节编码以11110开头(0xF0),后面跟着3个以10开头的字节
  • 选项B:0xF0 (11110000) + 0x90 (10010000) + 0x80 (10000000) + 0x80 (10000000) 符合4字节编码规则
  • 其他选项不符合UTF-8编码规则

第3题

题目:在8位二进制原码表示中,八进制数-5的二进制形式是什么( )

  • A. 10000101
  • B. 11111010
  • C. 11111011
  • D. 00000101

答案:A

解析

  • 八进制5的二进制是101
  • 8位表示:00000101
  • 原码表示负数:最高位为1,其余位不变 → 10000101

第4题

题目:十进制数111.111的二进制表示可以是下面的( )。

选项

  • A. 1101111.0001110001
  • B. 1101110.1001110001
  • C. 1101111.1001110001
  • D. 1101111.0011110001

答案:A

解析

  • 整数部分111:1101111(除2取余法)
  • 小数部分0.111:0.0001110001(乘2取整法,无限循环,近似)
  • 组合:1101111.0001110001

第5题

题目:在C++中,补码的主要作用是()

  • A. 提高浮点数的精度
  • B. 简化整数的加减法运算
  • C. 增加整数的表示范围
  • D. 优化内存分配

答案:B

解析

补码的主要优点是可以将减法运算转换为加法运算,简化了CPU的运算电路设计。

参考:【GESP】C++三级考试大纲知识点梳理, (1)二进制数据编码


第6题

题目:在C++中,一个8位有符号整数(使用补码表示)的范围是()

  • A. -128到127
  • B. -127到128
  • C. -256到255
  • D. 0到255

答案:A

解析

8位补码表示范围:-2^7到2^7-1,即-128到127。

参考:【GESP】C++三级考试大纲知识点梳理, (1)二进制数据编码


第7题

题目:在C++中,以下代码的输出是什么()

1
2
3
int a = -5;
unsigned int b = a;
cout << b;
  • A. -5
  • B. 5
  • C. 4294967291
  • D. 编译错误

答案:C

解析

  • -5的补码表示(32位):0xFFFFFFFB
    • 首先将-5转换为二进制:00000000 00000000 00000000 00000101
    • 然后取反:11111111 11111111 11111111 11111010
    • 最后加1:11111111 11111111 11111111 11111011 (0xFFFFFFFB)
  • 转换为无符号整数:4294967291
    • 由于是无符号整数,补码形式的二进制数直接被解释为正数
    • 即:11111111 11111111 11111111 11111011 = 4294967291
    • 可以理解为:2^32 - 5 = 4294967296 - 5 = 4294967291

第8题

题目:下列程序的作用是()

1
2
3
4
5
int main() {
    int decimal = 25;
    cout << oct << decimal;
    return 0;
}
  • A. 将十进制数转换成八进制数
  • B. 将八进制数转换成十进制数
  • C. 将二进制数转换成八进制数
  • D. 将八进制数转换成16进制数

答案:A

解析

oct操纵符将输出流设置为八进制输出模式,将十进制数25输出为八进制31。


第9题

题目:下面程序是将十进制数转换成十六进制数,横线处应该填入的是()

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
    int decimal = 255;
    ________________
    return 0;
}
  • A. cout « oct « decimal;
  • B. cout « decimal « decimal;
  • C. cout « hex « decimal;
  • D. 不能正确执行

答案:C

解析

这道题目考察C++输出流操纵符的使用。题目要求将十进制数转换为十六进制数,选项C是正确答案。原因如下:

  1. hex操纵符可以将输出流设置为十六进制输出模式
  2. 程序执行后,255将被转换为十六进制输出”ff”
  3. 其他选项说明:
    • A使用oct会输出八进制
    • B重复输出decimal没有意义
    • D的说法不正确,程序可以正确执行

第10题

题目:以下代码的说法正确的是什么()

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;

int main() {
    int a = @b1101;
    int b = @b1011;
    cout << (a ^ b);
    return 0;
}
  • A. 进行的是整体异或运算
  • B. 进行的是按位同或运算
  • C. 进行的是按位与运算
  • D. 进行的是按位异或运算

答案:D

解析

^是C++中的按位异或运算符。对于两个二进制数,按位异或运算的规则是:

  • 当对应位相同时,结果为0
  • 当对应位不同时,结果为1

在本题中:

  • @b1101 = 13(二进制1101)
  • @b1011 = 11(二进制1011)
  • 1101 ^ 1011 = 0110 = 6(十进制)

因此这段代码是在进行按位异或运算,输出结果为6。


第11题

题目:下面枚举法查找最大值索引程序中,横线处应该填写的是()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main() {
    int arr[] = {3, 7, 2, 9, 5};
    int maxIndex = 0;
    for (int i = 1; i < 5; i++) {
        ______
        {
            maxIndex = i;
        }
    }
    cout << maxIndex;
    return 0;
}
  • A. if (arr[maxIndex] > arr[i])
  • B. if (arr[i]-1 > arr[maxIndex])
  • C. if (arr[i]+1 > arr[maxIndex])
  • D. if (arr[i] > arr[maxIndex])

答案:D

解析

查找最大值索引的逻辑是:当当前元素大于已知最大值时更新索引。


第12题

题目:以下代码的功能是将数组中的奇数和偶数分别放在数组的前半部分和后半部分,横线处应该填入的是()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int left = 0, right = 4;
    while (left < right) {
        while (arr[left] % 2 == 1 && left < right) left++;
        ______
        if (left < right) {
            swap(arr[left], arr[right]);
        }
    }
    for (int i = 0; i < 5; i++) {
        cout << arr[i] << " ";
    }
    return 0;
}
  • A. while (arr[left] % 2 == 0 && left < right) right–;
  • B. while (arr[right] % 2 == 0 && left < right) left–;
  • C. while (arr[right] % 2 != 0 && left < right) right–;
  • D. while (arr[right] % 2 == 0 && left < right) right–;

答案:D

解析

这道题目考察双指针算法。代码使用两个指针left和right分别从数组两端向中间移动:

  1. left指针从左向右找第一个偶数
  2. right指针从右向左找第一个奇数
  3. 找到后交换这两个数
  4. 重复这个过程直到left和right相遇

因此空白处需要移动right指针,直到找到一个奇数。选项D while (arr[right] % 2 == 0 && left < right) right-- 正确实现了这个逻辑。


第13题

题目:下面程序最后能够得到HelloC++的是()

1
2
3
4
5
int main() {
    string str = "HelloWorld";
    cout << str;
    return 0;
}
  • A. str.replace(0, 5, “C++”);
  • B. str.replace(5, 5, “C++”);
  • C. str.replace(1, 5, “C++”);
  • D. str.replace(4, 5, “C++”);

答案:B

解析

replace(5,5,”C++”)表示从索引5开始替换5个字符(”World”)为”C++”,得到”HelloC++”。


第14题

题目:想要得到字符串world,下面程序横线处应该填入的是()

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>
using namespace std;

int main() {
    string str = "HelloC++";
    ______
    ______
    return 0;
}
  • A. str.insert(4, “World”); cout « str.substr(4, 4);
  • B. cout « str.substr(5, 5);
  • C. str.insert(“World”); cout « str.substr(5, 5);
  • D. str.insert(5, “World”); cout « str.substr(5, 5);

答案:D

解析

解析

这道题目考察string类的insert和substr方法的使用:

  1. str.insert(5, “World”):在索引5的位置插入字符串”World”
    • 原字符串:”HelloC++”
    • 插入后:”HelloWorldC++”
  2. str.substr(5, 5):从索引5开始截取5个字符
    • 截取”World”部分

其他选项分析:

  • A:在索引4插入会得到”HellWorldoC++”,substr(4,4)会得到”Well”
  • B:没有插入操作,直接截取会得到”C++”
  • C:insert方法参数不正确

因此D是正确答案,可以得到”world”。


第15题

题目:有n个正整数,假设一个正整数是美丽数字当且仅当该正整数是9的倍数但不是8的倍数。下面的程序是编写计算n个正整数中美丽数字的数量,横线处应该填入的是()

1
2
3
4
5
6
for (int i = 1; i <= n; i++) {
    cin >> a;
    if (______) {
        cnt++;
    }
}
  • A. if (a % 9 != 0 && a % 8 != 0)
  • B. if (a % 9 == 0 & a % 8 == 0)
  • C. if (a % 9 == 0 && a % 8 != 0)
  • D. if (a % 9 == 0 & a % 8 != 0)

答案:C

解析

这道题目考察美丽数字的判断条件:

  1. 美丽数字的定义:
    • 是9的倍数(a % 9 == 0)
    • 不是8的倍数(a % 8 != 0)
  2. 选项分析:
    • A:条件相反,判断既不是9的倍数又不是8的倍数
    • B:使用单个&是位运算符,不是逻辑与,且条件错误
    • C:正确实现了美丽数字的判断条件
    • D:使用单个&是位运算符,虽然条件正确但语法错误

因此C是正确答案:if (a % 9 == 0 && a % 8 != 0)


二、判断题(每题2分,共20分)

判-第1题

题目:判断一个三角形是否成立的条件只有:任意两边长度之和大于第三条边的长度

答案:错误❌

解析

判断一个三角形是否成立有两种判断条件:

  1. 任意两边之和大于第三边
  2. 任意两边之差小于第三边

任选其一即可。


判-第2题

题目:这段程序进行的是判断一个从键盘输入的字符的ASCII是否是奇数,若是,输出YES,否则,输出NO

1
2
3
4
5
6
7
int main() {
    char x;
    scanf("%c", &x);
    int ASCII = (int)x;
    cout << (x & 1 ? "YES" : "NO") << '\n';
    return 0;
}

答案:正确✅

解析

这段代码使用位运算符&来判断ASCII码的奇偶性。x & 1 的操作会保留x的最低位,其他位都置为0。如果最低位是1则为奇数,如果最低位是0则为偶数。这种方法比使用取模运算更高效。


判-第3题

题目:普通闰年:公历年份是 4 的倍数,且不是 100 的倍数的,为闰年(如 2004 年、2020 年等就是闰年)。

世纪闰年:公历年份是整百数的,必须是 400 的倍数才是闰年(如 1900 年不是闰年,2000 年是闰年)。

下面程序是判断是否是闰年的正确程序

1
2
3
cin>>n;
cout<<((n%4==0&&n%100!=0)||(n%400==0))?1:0;
return 0;

答案:正确✅

解析: 闰年判断条件正确:能被4整除但不能被100整除,或能被400整除。


判-第4题

题目:C++语句cout<<(n%15==0? "YES":"NO"); 能够判断一个整数能否被3和5同时整除

答案:正确✅

解析

n%15==0等价于n能被3和5同时整除(因为15=3×5)。


判-第5题

题目:有n个同学,从中抽取任意个人数来参加学校组织的大合唱,共有2的n次幂个方法

答案:正确✅

解析: 对于每个同学来说,都有”参加”和”不参加”两种选择。当有n个同学时:

  1. 第一个同学有2种选择
  2. 第二个同学也有2种选择
  3. 依此类推,每个同学都有2种选择

根据乘法原理,总的选择方法数为:2 × 2 × … × 2(n个2相乘)= 2^n

例如:

  • 当n=1时,方法数为2^1=2
  • 当n=2时,方法数为2^2=4
  • 当n=3时,方法数为2^3=8

这也可以从二进制的角度理解:n个同学的参与情况可以用一个n位二进制数表示,其中1表示参加,0表示不参加。n位二进制数共有2^n种不同的组合。


判-第6题

题目:若将⼀个正整数化为⼆进制数,在此⼆进制数中,我们将数字 1 的个数是偶数的这类⼆进制数称为 A 类数,否则就称其为 B 类数。

例如: (13) 10 =(1101) 2 ,其中 1 的个数为 3则称此数为 B 类数; (10) 10 =(1010) 2 ,其中 1 的个数为 2,称此数为 A 类数; 判断(2025)10化为⼆进制后,1的个数为偶数个,因此2025为A类数。

答案:正确✅

解析

2025转换为二进制:

  1. 2025 ÷ 2 = 1012 余 1
  2. 1012 ÷ 2 = 506 余 0
  3. 506 ÷ 2 = 253 余 0
  4. 253 ÷ 2 = 126 余 1
  5. 126 ÷ 2 = 63 余 0
  6. 63 ÷ 2 = 31 余 1
  7. 31 ÷ 2 = 15 余 1
  8. 15 ÷ 2 = 7 余 1
  9. 7 ÷ 2 = 3 余 1
  10. 3 ÷ 2 = 1 余 1
  11. 1 ÷ 2 = 0 余 1

因此2025的二进制表示为11111100001,其中1的个数为8个,是偶数个,所以2025是A类数。


判-第7题

题目:该段程序将n不停地除以2,并输出此时的商和余数,直到n=0为止。

1
2
3
4
5
6
long long n;
cin >> n;
while(n != 0) {
    cout << n/2 << ' ' << n%2 << '\n';
    n /= 2;
}

答案:正确✅

解析: 程序确实实现了将n不断除以2并输出商和余数的功能。


判-第8题

题目:两个13进制的数A和B,在10进制下分别表示10和11。(A+B)13=(18)13,也就是说13进制数A加上13进制数B,和是13进制数18。

答案:正确✅

解析

10+11=21,21在13进制中是1×13+8=18(因为21÷13=1余8)。


判-第9题

题目:k进制,逢k进第二位,进百位,进千位;

答案:正确✅

解析

k进制数的计数规则与十进制类似,只是进位的基数从10变成了k。

参考:【GESP】C++三级考试大纲知识点梳理, (2)数据的进制转换


判-第10题

题目:CCF(十九进制) = 21AC(十三进制)(不区分大小写)

答案:错误❌

解析

需要将两边转换为同一进制比较:

  • CCF(19) = 12×19² + 12×19 + 15 = 12×361 + 228 + 15 = 4332 + 243 = 4575
  • 21AC(13) = 2×13³ + 1×13² + 10×13 + 12 = 2×2197 + 169 + 130 + 12 = 4394 + 311 = 4705 不相等,因此题目说法错误。

所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code

GESP各级别考纲要点、知识拓展和练习题目清单详见C++学习项目主页

luogu-”系列题目已加入洛谷Java、C++初学团队作业清单,可在线评测,团队名额有限,欢迎加入。

bcqm-”系列题目可在编程启蒙题库进行在线评测。

欢迎加入Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答

欢迎加入C++ GESP/CSP认证学习QQ频道,考试资源总结汇总

欢迎加入C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助

本文由作者按照 CC BY 4.0 进行授权