
一、单选题 每题 2 分,共 30 分
| 1 | 答案:A 需要返回整数,且参数为两个整型。A 满足要求。B 返回类型为 void,不能返回整数值;C 参数未指定类型;D 返回类型为 void 与 return 矛盾。 |
| 2 | 答案:B 形参在函数定义时声明,实参在调用时传递。A 描述反了,把形参和实参的定义搞混了。 |
| 3 | 答案:A 全局 var = 100。main() 先输出 100;function() 中局部 var = 200,输出 200,::var 为全局 100;返回后全局 var += 100 变为 200,最后输出 200。完整输出为 100 200 100 200。考点:全局变量与局部变量的作用域以及作用域解析运算符 ::。 |
| 4 | 答案:B p 初始指向 arr[0],p++ 后指向 arr[1],*p 即 9。指针自增后指向下一个元素,解引用得到对应值。 |
| 5 | 答案:D p = q; 使指针 p 指向 q 所指的对象,即 y 的地址。指针赋值改变的是指针的指向,而不是所指对象的值。 |
| 6 | 答案:D new Student[20] 返回 Student* 类型,不能直接赋值给 Student 变量。应使用 Student* students = new Student[20];。这是动态内存分配中常见的类型匹配问题。 |
| 7 | 答案:D 结构嵌套可以减少命名冲突,但仍需合理控制嵌套层次。过度嵌套会降低可读性和维护性,D 说可以不必控制嵌套层次是错误的。 |
| 8 | 答案:A updateScore 的参数是按值传递的结构体,修改不影响实参,因此 stu.score 仍为 80,输出 Tom 80。结构体作为参数默认是值传递。 |
| 9 | 答案:C 冒泡排序、选择排序、插入排序都是原地排序算法,不需要额外数组,空间复杂度均为 O(1)。C 正确。 |
| 10 | 答案:A 冒泡排序每轮将最大元素移至末尾,内层循环范围应逐轮缩小,故 j < n - i - 1;相邻逆序则交换,用 swap(nums[j], nums[j + 1])。 |
| 11 | 答案:A 插入排序升序,将当前元素 key 与前面元素比较,若前面的元素大则后移,条件应为 arr[j] > key;退出循环后合适位置为 j+1,填入 arr[j + 1] = key。 |
| 12 | 答案:A 选择排序无论数据初始状态如何,都需要进行 n(n-1)/2 次比较,最好和最坏时间复杂度都是 O(n^2)。这是选择排序的特点。 |
| 13 | 答案:A 斐波那契数列递归定义为 F(n) = F(n-1) + F(n-2),故填入 fibonacci(n - 1) + fibonacci(n - 2)。这是最经典的递归定义。 |
| 14 | 答案:A 单层循环遍历数组求和,操作次数与 n 成正比,时间复杂度为 O(n)。线性时间复杂度的典型场景。 |
| 15 | 答案:C ifstream 用于读取,ofstream 用于写入;文件使用后必须关闭以释放资源;同一流对象不能同时读写,但可通过不同对象分别操作。C 正确,全面概括了文件操作的核心要点。 |
二、判断题 每题 2 分,共 20 分
| 16 | 正确 函数封装可重用的代码,是 C++ 的核心概念。通过函数可以将复杂问题分解为若干小问题逐个解决。 |
| 17 | 错误 C++ 标准要求函数必须显式声明返回类型,不能省略。与 C 语言不同,C++ 没有默认 int 的规则,省略返回类型会编译报错。 |
| 18 | 正确 struct 的成员默认访问权限为 public,这是 struct 与 class(默认 private)的重要区别之一。 |
| 19 | 错误 二维数组定义时,列(第二维)的大小必须确定;行(第一维)的大小可以省略并由初始化列表推断。题目说反了——列不能动态变化。 |
| 20 | 正确 多维数组作为参数时,除第一维外,其他维度的大小必须指定。int arr[3][] 不合法,编译器无法确定偏移量。 |
| 21 | 正确 递归函数必须有终止条件(基线条件),否则会造成无限递归,最终导致栈溢出。这是递归的基本要求。 |
| 22 | 正确 当数组已经有序时,添加交换标志优化的冒泡排序在第一轮遍历中无交换即可提前结束,时间复杂度为 O(n)。常见教材认为冒泡排序最好情况为 O(n)。 |
| 23 | 错误 对 {3, 1, 4, 1, 5} 进行升序选择排序,第一轮找到最小值 1(通常取第一个遇到的,位于索引 1),与首元素交换后数组变为 {1, 3, 4, 1, 5},不是 {1, 1, 4, 3, 5}。 |
| 24 | 错误 throw "error" 抛出的是 const char* 类型异常,而 catch (int e) 只能捕获 int 类型异常,该异常不会被捕获,程序会异常终止。类型不匹配时 catch 无法捕获。 |
| 25 | 正确 ofstream 打开文件,通过 << 写入字符串并关闭文件,代码正确实现了文件的写入操作。 |
三、编程题
题目 A · 字符排序
有 n 个仅含小写字母的字符串,要把它们按某种顺序拼接成一个大字符串 t,要求 t 满足非递减:即对于任意 j < i,都有 t[j] <= t[i](按字母表顺序)。问是否存在这样的排列。
参考代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
while(t--){
int n;
string s[110];
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
}
sort(s+1,s+n+1);
string str="";
for(int i=1;i<=n;i++){
str+=s[i];
}
bool ans=1;
for(int i=1;i<=str.size()-1;i++){
if(str[i]<str[i-1]){
ans=0;
break;
}
}
if(ans)cout<<1<<endl;
else cout<<0<<endl;
}
return 0;
}
解题思路:
| 1 | 检查内部有序性:遍历每个字符串,若发现有相邻字符递减(即 s[k] > s[k+1]),直接输出 0,因为无论怎么排列内部都无法满足非递减。 |
| 2 | 提取首尾字符:对每个字符串,最小字符即首字符 l_i(因为已内部有序),最大字符即尾字符 r_i。 |
| 3 | 排序区间:将所有 n 个区间按首字符 l_i 从小到大排序;若首字符相同,则按尾字符 r_i 从小到大排序。 |
| 4 | 验证可拼接性:扫描排序后的区间序列,检查是否满足 r_i <= l_{i+1}(i = 1, 2, ..., n-1)。若全部满足,排列即为合法方案,输出 1;否则输出 0。 |
题目 B · 画布裁剪
输入一个 n 行 m 列的字符画布,以及裁剪区域的行范围 [ax, bx] 和列范围 [ay, by],输出裁剪后的子画布。
参考代码:
#include<bits/stdc++.h>
using namespace std;
char c[105][105];
int main() {
int n,m;
cin>>n>>m;
int ax,bx,ay,by;
cin>>ax>>bx>>ay>>by;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
cin>>c[i][j];
}
}
for(int i=ax; i<=bx; i++) {
for(int j=ay; j<=by; j++) {
cout<<c[i][j];
}
cout<<endl;
}
}
解题思路:
| 1 | 输入基本参数:读入画布高度 n、宽度 m,以及保留区域的行范围 [ax, bx] 和列范围 [ay, by]。注意题目行列从 1 开始计数。 |
| 2 | 存储画布:使用二维字符数组 c[105][105] 逐字符读入整个画布,行列下标从 1 到 n/m。 |
| 3 | 按范围输出:外层循环 i 从 ax 到 bx(行),内层循环 j 从 ay 到 by(列),逐字符输出 c[i][j],每行结束后换行。 |
| 4 | 复杂度分析:时间复杂度 O(n*m),即遍历整个画布一次。空间复杂度 O(n*m) 用于存储画布。这是典型的二维数组遍历题目。 |
备考提示
本次四级模拟题涵盖:函数定义与调用、全局/局部作用域、指针与动态内存分配、结构体与嵌套、三大排序算法(冒泡/选择/插入)、时间复杂度分析、递归思想、文件流操作等核心考点。建议重点掌握:值传递与指针传递的区别、new/delete 的正确使用、排序算法的手写实现、以及二维数组的遍历技巧。
