CCF-GESP 等级考试 2024年9月认证C++四级真题解析

2024年9月真题

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


正确答案:A

考察知识点:函数的定义与调用

解析:在 C++ 中,函数定义的格式为 "返回值类型 函数名 (参数类型 参数名,...) { 函数体 }"。选项 A 的int add(int a, int b) { return a + b; }符合 "返回整数值、接受两个整数参数" 的要求。答案为A。


正确答案:B

考察知识点:函数的定义与调用、形参与实参

解析:在 C++ 中,形参是函数定义时指定的参数(用于接收实参的值),实参是函数调用时传递给形参的具体值。选项 B 的描述符合这一关系。答案为B。



正确答案:A

考察知识点:函数的定义与调用、变量的作用域

解析:main函数中先输出var(全局变量,值为100)。

调用function函数时,输出局部var(200)和全局var(100, :; 访问到的是全局变量)。

main函数中var += 100后,全局var变为200,输出200。

因此最终输出为100 200 100 200。答案为A。


正确答案:B

考察知识点:数组、C++指针类型的概念及基本应用

解析:数组arr的首地址由p指向,执行p++后,p指向数组的第二个元素(即9)。*p取值该元素,因此输出9。答案为 B。


正确答案:D

考察知识点:C++指针类型的概念及基本应用

解析:代码中p初始指向x的地址,q指向y的地址。执行p = q;后,p的指向被修改为y的地址。答案为D。


正确答案:A

考察知识点:结构体

解析:在 C++ 中,结构体的正确定义格式为struct 结构体名 { 成员列表; };。选项 A 的struct student { char name[20]; int age; };符合要求,正确定义了包含name字符数组和age整数的student结构体。答案为A。



正确答案:B

考察知识点:二维数组与多维数组基本应用

解析:在 C++ 中,二维数组的声明格式为类型 数组名[行数][列数]。选项 B 的int arr[3][4];符合 "3 行 4 列" 的声明要求。答案为B。


正确答案:D

考察知识点:二维数组与多维数组基本应用

解析:二维数组arr[3][4]中,arr[0]是第 0 行的数组,包含 4 个int元素。每个int占 4 字节,因此arr[0]占用的内存为4 × 4 = 16字节。答案为D。


正确答案:A

考察知识点:递推算法

解析:阶乘的递推逻辑是result = result × i(初始result=1,依次乘以2,3,...,n)。选项 A 的result *= i;符合这一逻辑。答案为A。


正确答案:B

考察知识点:排序算法

解析:排序算法的稳定性:排序算法执行后,原始数组中相等元素的相对顺序保持不变,则该算法为稳定排序;反之则为不稳定排序。答案为B。


正确答案:C

考察知识点:排序算法

解析:冒泡排序的核心思想是:通过重复遍历待排序序列,每次比较相邻的两个元素,若顺序错误则交换它们的位置,直到没有元素需要交换为止。

冒泡排序的内层循环需遍历到当前未排序区间的末尾(由外层循环变量i控制)。选项 C 的for (int j = 0; j < i; j++)符合逻辑:每次外层循环i递减,内层循环遍历0到i-1的区间,对相邻元素进行比较交换。答案为C。


正确答案:A

考察知识点:排序算法、简单算法复杂度的估算

解析:该冒泡排序代码的时间复杂度分析如下:

最坏情况与平均情况:外层循环执行 n−1 次(n 为数组元素个数),内层循环在第 i 次外层循环时执行 i 次。总操作次数为 1+2+⋯+(n−1)= n(n−1)/2,因此时间复杂度为 O(n2)O(n^2)O(n2)。

最好情况:若数组已完全有序,内层循环的flag会提前终止循环,此时只需遍历一次数组,时间复杂度为 O(n)O(n)O(n)。

综上,该冒泡排序的平均、最坏时间复杂度为 O(n2)O(n^2)O(n2),最好时间复杂度为 O(n)O(n)O(n)。答案为A。

对排序算法复杂度非常熟悉的同学,本题可直接作答。


正确答案:A

考察知识点:排序算法

解析:插入排序的算法思想是:将待排序数组分为已排序区间和未排序区间,初始时已排序区间只有第一个元素。然后依次从未排序区间取出元素,插入到已排序区间的合适位置,使已排序区间始终保持有序,重复此过程直到未排序区间元素为空,最终得到有序数组。

插入排序的核心逻辑是:对于当前元素base,向前遍历已排序区间,当nums[j] > base且j ≥ 0时,将nums[j]后移。选项 A 的while (j >= 0 && nums[j] > base)符合这一逻辑。答案为A。



正确答案:A

考察知识点:文件重定向与文件读写操作

解析:代码中通过cout.rdbuf(log_file.rdbuf())将cout的输出缓冲区重定向到log_file(对应log.txt文件)。因此,使用cout输出的内容会写入log.txt,选项 A 的cout << "This output will go to the log file." << endl;符合要求。答案为A。


正确答案:C

考察知识点:异常处理

解析:代码中y=0,调用divide(x,y)时触发除零异常,抛出runtime_error("division by zero error ")。catch块捕获该异常,输出"caught an exception: division by zero error"。答案为C。

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


正确答案:正确

考察知识点:C++指针类型的概念及基本应用

解析:代码中先定义int变量a并赋值10,再定义指针p并将其初始化为a的地址(&a),这是 C++ 中正确定义和初始化指针的方式。表述正确。


正确答案:正确

考察知识点:函数参数传递的概念

解析:在 C++ 中,引用是变量的别名,函数通过引用传递参数时,直接操作原变量的内存空间,因此允许函数修改传递给它的参数的值。表述正确。


正确答案:错误

考察知识点:C++指针类型的概念及基本应用

解析:指针的大小取决于系统的地址总线宽度(如 32 位系统指针占 4 字节,64 位系统占 8 字节),与所指向变量的数据类型大小无关。例如,int和double指针在同一系统中大小相同。表述错误。


正确答案:错误

考察知识点:二维数组与多维数组基本应用

解析:在 C++ 中,二维数组的行和列的大小在定义时都必须确定,不支持列的大小动态变化。例如int arr[3][4],行3和列4都需在定义时明确。表述错误。


正确答案:正确

考察知识点:递推算法

解析:递推算法的核心思想就是通过已知的初始状态,逐步推导当前状态与前一个或几个状态的关系(如斐波那契数列中f(n) = f(n-1) + f(n-2)),从而求解问题。因此该描述符合递推算法的定义。表述正确。

正确答案:错误

考察知识点:排序算法

解析:排序算法的稳定性:排序算法执行后,原始数组中相等元素的相对顺序保持不变,则该算法为稳定排序;反之则为不稳定排序。

选择排序,将待排序数组分为「已排序区间」和「未排序区间」,初始时已排序区间为空。每次从未排序区间中找到最小(或最大)元素,将其与未排序区间的第一个元素交换位置,此时该元素加入已排序区间。重复此过程,直到未排序区间为空。

选择排序是不稳定的排序算法。例如数组 [2, 2, 1],第一趟会将第 3 个1与第 1 个2交换,导致两个2的相对顺序改变。表述错误。


正确答案:错误

考察知识点:排序算法

解析:插入排序的算法思想是:将待排序数组分为已排序区间和未排序区间,初始时已排序区间只有第一个元素。然后依次从未排序区间取出元素,插入到已排序区间的合适位置,使已排序区间始终保持有序,重复此过程直到未排序区间元素为空,最终得到有序数组。

冒泡排序的核心思想是:通过重复遍历待排序序列,每次比较相邻的两个元素,若顺序错误则交换它们的位置,直到没有元素需要交换为止。

插入排序和冒泡排序的时间复杂度平均、最坏情况均为 O(n2)O(n^2)O(n2)(n 为元素个数)。二者时间复杂度等级相同,不存在 "插入排序时间复杂度总是比冒泡排序低" 的情况。表述错误。


正确答案:错误

考察知识点:异常处理

解析:在 C++ 中,若抛出异常后没有匹配的catch块捕获,程序会立即终止,并调用std::terminate函数(默认行为是调用abort终止程序)。表述错误。


正确答案:错误

考察知识点:递推算法、简单算法复杂度的估算

解析:该代码采用递推法(迭代方式)求斐波那契数列,通过for循环从第 2 项迭代到第n项,循环次数为n-1次,时间复杂度为 O(n)O(n)O(n)(线性级),而非指数级。表述错误。


正确答案:正确

考察知识点:函数参数传递的概念、C++指针类型的概念及基本应用

解析:在main函数中,定义int a = 10,并让指针p指向a的地址(int* p = &a)。

调用point( p )时,函数内的*p就是a的值10,执行*p * 2后返回20。

*p = point( p ) 将a的值更新为20,最后cout << *p 输出 a 的当前值20。表述正确。

三、编程题(每题25分,共50分)



本题考察:模拟算法、枚举算法、多测试样例处理

枚举所有的4行4列子矩阵,判断其是否满足条件

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int t, n, m;
//预设4行4列满足条件的矩阵 
//1、矩形的第 1 行和第 4 行只包含白色格子;
//2、矩形的第 2 行和第 3 行,只有第 1 个和第 4 个格子是白色的,其余格子都是黑色的; 
char match[4][4]={{'0', '0', '0', '0'},
				  {'0', '1', '1', '0'},
                  {'0', '1', '1', '0'},
				  {'0', '0', '0', '0'}};
char arr[101][101];
//通过和预设满足条件的矩阵进行比较,判断子矩阵是否满足条件 
bool check(int x1, int y1, int x2, int y2){
	for(int i=x1; i<=x2; i++){
		for(int j=y1; j<=y2; j++){
			if(arr[i][j] != match[i-x1][j-y1]) return false;
		}
	}
	return true;
}
int main() {
	cin>>t;
	while(t--) {
		cin>>n>>m;
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=m; j++) {
				cin>>arr[i][j];
			}
		}
		bool flag=0;
		//枚举所有的4行4列子矩阵
		//4行4列子矩阵左上角格子下标(x1, y1) 
		for(int x1=1; x1+3<=n; x1++) {
			for(int y1=1; y1+3<=m; y1++) {	
				int x2=x1+3, y2=y1+3;  //4行4列子矩阵右下角格子下标(x2, y2)
				//检查子矩阵是否满足要求 
                if(check(x1, y1, x2, y2)){
                	flag=true;
                	break;
				}
			}
			if(flag) break;
		}
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

提供另一种思路,利用前缀和求解,时间复杂度能再低一点,不过对本题来说,影响不大。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int t, n, m, prefix[101][101];
char arr[101][101];
int main() {
	cin>>t;
	while(t--) {
		cin>>n>>m;
		memset(prefix, 0, sizeof(prefix));
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=m; j++) {
				cin>>arr[i][j];
				prefix[i][j] = prefix[i][j-1]+prefix[i-1][j]-prefix[i-1][j-1]+(arr[i][j]-'0');
			}
		}
		bool flag=false;
		//枚举所有的4行4列子矩阵
		//4行4列子矩阵左上角格子下标(x1, y1) 
		for(int x1=1; x1+3<=n; x1++) {
			for(int y1=1; y1+3<=m; y1++) {
				int x2=x1+3, y2=y1+3; //4行4列子矩阵右下角格子下标(x2, y2)
				//计算子矩阵和 num 
				int num = prefix[x2][y2]-prefix[x2][y1-1]-prefix[x1-1][y2]+prefix[x1-1][y1-1];
				//如果子矩阵和为4,且只有四个特殊位置为黑格子,说明满足要求 
				if(num == 4 && arr[x1+1][y1+1]=='1' && arr[x1+1][y2-1]=='1' && arr[x2-1][y1+1]=='1' && arr[x2-1][y2-1]=='1') {
					flag=true;
					break;
				}
			}
			if(flag) break;
		}
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}


本题考察:排序算法、模拟算法。也是历史最简单了!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main() {
	int n, arr[101], q, l, r;
	cin>>n;
	for(int i=1; i<=n; i++) cin>>arr[i];
	cin>>q;
	while(q--){
		cin>>l>>r; 
		sort(arr+l, arr+r+1); //使用sort函数进行区间排序 
	}
	for(int i=1; i<=n; i++) cout<<arr[i]<<" ";
	return 0;
}
相关推荐
光头闪亮亮3 小时前
curl库应用-c++客户端示例及golang服务端应用示例
c++·go
微笑尅乐3 小时前
洗牌算法讲解——力扣384.打乱数组
算法·leetcode·职场和发展
Lei_3359673 小时前
[算法]背包DP(01背包、完全背包问题、多重背包、分组背包、混合背包问题、有依赖的背包问题等)
c++·算法
uesowys3 小时前
华为OD算法开发指导-比赛的冠亚季军
算法·华为od
天选之女wow3 小时前
【代码随想录算法训练营——Day48】单调栈——42.接雨水、84.柱状图中最大的矩形
算法·leetcode
不知名。。。。。。。。3 小时前
算法之动态规划
算法·动态规划
lingchen19063 小时前
MATLAB图形绘制基础(一)二维图形
开发语言·算法·matlab
hlpinghcg4 小时前
(全闭环)FUNC_FullCloseLoop
算法·电机·电机控制
朝新_4 小时前
【EE初阶】JVM
java·开发语言·网络·jvm·笔记·算法·javaee