2024年03月CCF-GESP编程能力等级认证C++编程四级真题

2024年05月13日

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

第 1 题 若函数声明为 int f(int &x){ x+=3; return x; } ,则对声明的变量 int a=3 ,下面哪个调用能够改变 a 的值( )。

A. f(&a) ;
B. f(*a) ;
C. f(a) ;
D. f(a-3) ;

答案:C 因为 f 函数期望一个 int 类型的引用,当传入 a 时,它实际上传递了 a 的引用,因此函数内部对 x 的修改会直接影响 a 的值。

第 2 题 下面C++代码执行后,输出的是( )。

int main()
{
	int x[]={2, 0, 2, 4};
	char geSP[]="Grade Examination of SP";
	cout << geSP[sizeof(x)] << endl;
	cout << endl;
	return 0;
}
A. G
B. e
C. n
D. P

答案:C 在代码中,sizeof(x) 返回数组 x 的大小,这里是 16 字节(4 个 int 元素,每个元素占 4 字节)。由于 geSP 是一个字符数组,可以将其视为一个以空字符结尾的字符串。sizeof(x) 超过了 geSP 字符数组的索引范围,因此访问到了 geSP 后面的内存。

根据 C++ 的字符串表示,输出结果将是 geSP[sizeof(x)] 后面的字符,即 “Grade Examination of SP” 后面的字符,即 ‘n’。因此,答案是 C. n。

第 3 题 下面C++代码执行后输出是( )。

int foo(float *f)
{
	return int(*f*2);
}
int main()
{
	float fnum[10]={1.1};
	fnum[1]=foo(fnum);
	cout << fnum[0]+fnum[1] << endl;
	cout << endl;
	return 0;
}
A. 1
B. 1.1
C. 3
D. 3.1

答案:D 在代码中,首先定义了一个名为 foo 的函数,它接受一个 float 类型的指针作为参数,并返回该指针指向的值乘以 2 的整数部分。

在 main 函数中,定义了一个名为 fnum 的 float 数组,并初始化第一个元素为 1.1。然后,调用 foo(fnum),将 fnum 数组的地址传递给 foo 函数,并将函数的返回值赋给 fnum[1]。根据 foo 函数的实现,fnum[1] 的值将是 fnum[0]2 的整数部分,即 12,结果为 2。

接下来,在输出语句 cout << fnum[0]+fnum[1] << endl; 中,将 fnum[0] 和 fnum[1] 相加,即 1.1 + 2,结果为 3.1。

因此,答案是 D. 3.1。

第 4 题 对二维数组 int arr[3][16]; ,则 arr[1] 占用内存的大小为( )字节。

A. 4
B. 16
C. 48
D. 64

答案:D 对于二维数组 int arr[3][16]arr[1] 表示二维数组的第二行,它是一个长度为 16 的一维数组。

一维数组的大小可以通过以下公式计算:sizeof(元素类型) * 数组长度。

在这种情况下,arr[1] 是一个 int 类型的一维数组,长度为 16。假设 int 类型占用 4 个字节,则 arr[1] 占用的内存大小为 4 * 16 = 64 字节。

因此,答案是 D. 64

第 5 题 对二维数组 int arr[3][16]; ,若 arr 的地址是 0x28cbc0 ,则 arr[1] 的值是( )。

A. 0x28cbc4
B. 0x28cbd0
C. 0x28cc00
D. 不确定

答案:C 对于二维数组 int arr[3][16],假设 int 类型占用 4 个字节。

给定 arr 的地址为 0x28cbc0,arr[0] 的地址即为 arr 的地址,arr[1] 的地址应该是 arr[0] 的地址加上 arr[0] 的大小。

arr[0] 的大小为 16 个 int,即 16 * 4 = 64 个字节。因此,arr[1] 的地址应该是 0x28cbc0 + 64 = 0x28cc00。

因此,答案是 C. 0x28cc00。

第 6 题 下面C++代码执行后输出是( )。

int main()
{
	char *p="I love GESP!";
	cout << p+5 << endl;
	cout << endl;
	return 0;
}
A. e
B. I lov
C. e GESP!
D. GESP!

答案:C 在代码中,p 是一个指向字符的指针,指向字符串常量 “I love GESP!” 的首字符 ‘I’。

p+5 表示将指针 p 向后移动 5 个字符的位置。由于一个字符占用一个字节,移动 5 个字符相当于移动 5 个字节。

因此,输出 p+5 将从字符串 “I love GESP!” 的第 6 个字符开始输出,即 “e GESP!”。

因此,答案是 C. e GESP!。

第 7 题 下面C++代码执行以后输出的是( )。

int rc=5;
int main()
{
	int rc;
	cout << ++rc << endl;
	cout << endl;
	return 0;
}
A. 0
B. 1
C. 6
D. 不确定

答案:D 在代码中,存在两个名为 rc 的变量。一个是全局变量 int rc=5;,另一个是在 main 函数内部定义的局部变量 int rc;。

在 cout 语句中,++rc 表示先对局部变量 rc 进行自增操作。由于局部变量 rc 没有被初始化,它的初始值是不确定的。

因此,输出结果取决于局部变量 rc 的初始值。由于初始值不确定,所以输出结果也是不确定的。

第 8 题 下面C++函数中采用的算法是( )。

int fib(int n)
{
	int i, f[n]={0, 1};
	for(int i=2; i<=n; i++)
		f[i]=f[i-1]+f[i-2];
	return f[n];
}
A. 递推
B. 递归
C. 迭代
D. 循环

答案:A 这个函数 fib 实现的算法是递推(A选项),但更具体地说,它使用了循环(D选项)来实现递推的过程。不过,如果我们从算法设计的角度来看,它属于递推算法。

第 9 题 插入排序在最好情况下的时间复杂度是( )。

A.O(1)
B.O(N/2)
C.O(N)
D.O(N^2)

答案:C 插入排序的基本思想是将一个数据元素插入到已经排序好的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。但在最好情况下,即输入数据已经是有序的情况下,插入排序只需要遍历一次数据,每个元素都只需比较一次就能确定其位置,因此时间复杂度是线性的,即O(N)。

第 10 题 在如下的C++代码执行后,设第11和12行的输出地址值分别为 X 和 Y ,则下面正确的是( )。

struct pass{
	int no;
	char name[20];
	int level;
};
int main()
{
	struct pass XiaoYang;
	cout << "&XiaoYang=" << &XiaoYang << endl; //第11行
	cout << "&(XiaoYang.no)=" << &(XiaoYang.no) << endl; //第12行
	cout << endl;
	return 0;
}
A. X>Y
B. X==Y
C. X<Y
D. 不确定

答案:B 在C++中,结构体(struct)中的成员变量在内存中是顺序排列的。对于给定的pass结构体,成员变量no、name和level在内存中是连续存放的,其中no是第一个成员变量。

现在考虑XiaoYang这个结构体变量,它在内存中有一个起始地址,即&XiaoYang。而XiaoYang.no作为结构体中的第一个成员变量,它的地址就是XiaoYang的起始地址。

因此,对于第11行和第12行的输出,我们有:

&XiaoYang 是结构体XiaoYang的起始地址。 &(XiaoYang.no) 是结构体XiaoYang中成员变量no的地址,由于no是第一个成员变量,所以它的地址与结构体的起始地址相同。 所以,X(即&XiaoYang)和Y(即&(XiaoYang.no))的值是相等的。

第 11 题 如果文件 1.txt 中的内容如下,则执行下面C++代码时,注释了 #### 那行代码所输出的 x 的值为()。

50 2024 3.16 I
love
GESP!
int main()
{
	ifstream fin;
	string line;
	int x;
	fin.open("1.txt",ios::in);
	for (int i=0; i< 2; i++){
		fin >> line;
		cout << line << endl;
	}
	fin>>x;
	cout << x << endl; //####
	cout << endl;
	return 0;
}
A. 5
B. 2024
C. 3
D. 0

答案:C 根据给定的代码和文件 “1.txt” 的内容,按照空格和换行符进行分割,第三个字符串是 “3.16”。

在注释了 “####” 的那行代码后,代码会尝试将该字符串转换为整数,并将其存储在变量 x 中。

由于 “3.16” 无法直接转换为整数,C++ 中的转换规则会将其截断为整数部分,即将 “3” 存储到 x 中。

因此,答案是 C. 3。

第 12 题 执行下列C++代码时输出中的第2行是( )。

int main()
{
	char *s[]={(char*)"2024",(char*)"3.16",(char*)"GESP"};
	for (int i=0; i< 2; i++){
		cout << *s+i << endl;
	}
	cout << endl;
	return 0;
}
A. 2024
B. 3.16
C. 024
D. 3

答案:C 首先,我们来分析这段C++代码。

代码定义了一个字符指针数组 s,其中包含三个字符串字面量的地址。

然后,有一个 for 循环,其循环条件是 i < 2,这意味着循环将执行两次。

在循环体中,有一行输出代码:cout << *s+i << endl;

但这里有一个常见的误解或错误。代码的本意可能是想输出数组 s 中的每个字符串,但是实际上,由于操作符的优先级问题,*s+i 并不是按照预期那样工作的。

*s 取出的是数组 s 的第一个元素的地址,即字符串 “2024” 的地址。然后,+i 是在这个地址上加上 i 个字节的偏移量,而不是跳转到数组 s 的下一个元素。

因此,当 i=0 时,*s+i 仍然是 “2024” 的地址,输出是 “2024”。

当 i=1 时,*s+i 是 “2024” 地址后第一个字符 ‘2’ 的地址加上1个字节,即指向了 ‘0’。但由于 cout 在输出时,会将其视为字符串的起始地址,并尝试输出从这个地址开始直到遇到空字符(null terminator)\0 的所有字符,所以实际上输出的是从 ‘0’ 开始到 “2024” 字符串结束的所有字符,即 “024”。

所以,输出中的第2行是 C. 024。

第 13 题 C++语言中下面哪个关键字能够限定对象的作用域( )。

A. extern
B. static
C. inline
D. public

答案:B 在C++语言中,关键字 static 可以用于限定对象的作用域。

当 static 用于全局变量时,它将限定该变量的作用域为当前文件,即只能在当前文件中访问该变量,不能被其他文件访问。

当 static 用于类的成员变量或成员函数时,它将限定该成员的作用域为类的范围,而不是对象的范围。这意味着该成员可以在类的所有对象之间共享,并且可以直接通过类名访问,而不需要实例化对象。

因此,static 关键字能够限定对象(或成员)的作用域。

因此,答案是 B. static。

第 14 题 小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是( )。

A. 小程序
B. 计时器
C. 操作系统
D. 神话人物

答案:C 鸿蒙(HarmonyOS)是华为公司开发的一款分布式操作系统。它旨在为不同设备提供统一的操作系统平台,实现设备间的无缝协同工作。

鸿蒙操作系统具有分布式架构和轻量级设计,能够在不同的设备上运行,包括智能手机、平板电脑、智能手表、智能电视、智能家居设备等。它提供了统一的开发框架,使开发者能够更方便地开发应用程序,并实现跨设备的无缝体验。

因此,鸿蒙是一款操作系统,不是小程序、计时器或神话人物。

第 15 题 中国计算机学会(CCF)在2024年1月27日的颁奖典礼上颁布了王选奖,王选先生的重大贡献是( )。

A. 制造自动驾驶汽车
B. 创立培训学校
C. 发明汉字激光照排系统
D. 成立方正公司

答案:C 中国计算机学会(CCF)在2024年1月27日的颁奖典礼上颁布的王选奖,王选先生的重大贡献是C. 发明汉字激光照排系统。

王选先生是汉字激光照排系统的发明者,这一系统为中国印刷技术带来了第二次革命,废除了沿用数百年的铅字印刷,使中文印刷业告别了“铅与火”,大步跨进“光与电”的时代。汉字激光照排系统占领了99%的国内报业市场以及90%的海外华文报业市场,为中国印刷业的发展做出了巨大贡献。因此,王选先生因其在此领域的重大贡献而获得了王选奖。

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

第 16 题 对 int a[]={2,0,2,4,3,1,6} ,执行第一趟选择排序处理后 a 中数据变为 {0,2,2,4,3,1,6} 。( )

答案:正确 选择排序是一种简单的排序算法,它的基本思想是找到数组中的最小元素,并将其与数组的第一个元素交换位置,然后在剩下的元素中寻找最小元素并进行交换,以此类推。

对于给定的数组 int a[]={2,0,2,4,3,1,6},执行第一趟选择排序时,算法会找到数组中的最小元素,即 0,并将其与数组的第一个元素 2 进行交换。所以第一趟处理后,数组变为 {0,2,2,4,3,1,6}。

因此,判断题的答案是正确的。

第 17 题 如果待排序数据不能都装进内存,需要使用外排序算法。( )

答案:正确 如果待排序的数据量太大,无法全部装进内存中进行排序,就需要使用外排序算法。

外排序是一种针对大规模数据的排序方法,它通过利用外部存储(如磁盘)来处理数据,将数据分为多个块或段,将每个块加载到内存中进行排序,然后将排序好的数据写回到磁盘上。多次读取和写入磁盘的操作使得外排序适用于数据量超过内存容量的情况。

外排序算法通常使用多路归并排序(Multiway Merge Sort)来完成排序过程,即将多个有序的子序列合并成一个有序的序列。

第 18 题 定义变量 int a=5 , 则 cout << &++a 会输出 6 。( )

答案:错误 在 C++ 中,对变量进行前置递增操作(++a)会先增加变量的值,然后返回递增后的值。而取地址运算符(&)用于获取变量的内存地址。

在给定的代码中,对变量 a 进行前置递增操作后,a 的值会变为 6。然后,使用 cout 输出表达式 &++a,即输出变量 a 的递增后的内存地址。

然而,根据 C++ 的语法规则,在 cout 输出变量的地址时,会将其转换为相应的指针类型进行输出。因此,表达式 &++a 的输出结果将是指向变量 a 的指针值,而不是递增后的值。

第 19 题 两个函数之间可以使用全局变量来传递数据。 ( )

答案:正确 在 C++ 中,全局变量是在函数外部定义的变量,其作用域覆盖整个程序。因此,全局变量可以在不同的函数之间共享和传递数据。

通过在函数外部定义全局变量,可以在程序中的任何地方访问和修改该变量的值。这意味着不同的函数可以通过访问和修改全局变量来进行数据的传递和共享。

需要注意的是,在使用全局变量传递数据时,需要注意避免数据竞争和不可预测的副作用。全局变量的使用应该谨慎,以确保正确性和可维护性。

第 20 题 定义数组 int a[2024][3][16]={2,0,2,4,3,1,6} ,则 cout << a[2023][2][15] 的结果不确定。()

答案:错误 对于给定的数组 int a[2024][3][16],索引范围是从 0 到 2023,从 0 到 2,从 0 到 15。

因此,cout << a[2023][2][15] 表示访问数组中的最后一个元素,即第 2024 组、第 3 个元素、第 16 个元素。根据数组的定义,该元素是有效的。

第 21 题 在C++语言中,函数的参数为指针时,可以在函数内部修改该参数的值。( )

答案:错误

第 22 题 在C++语言中 try 子句里抛出的结构体等类型的异常无法被 catch 捕获。( )

答案:错误 在 C++ 中,try-catch 机制用于异常处理。try 子句用于包裹可能会抛出异常的代码块,而 catch 子句用于捕获并处理抛出的异常。

C++ 的异常处理机制允许抛出不同类型的异常,包括结构体、类对象、基本数据类型等。当 try 子句中的代码抛出异常时,catch 子句会尝试匹配异常类型并进行处理。

无论是使用基本数据类型还是自定义的结构体,catch 子句都可以捕获并处理相应类型的异常。通过在 catch 子句中指定异常类型,可以捕获并处理特定类型的异常。

第 23 题 C++语言中 cout << 9^2 << endl; 会输出81。( )

答案:错误 在 C++ 中,运算符 ^ 表示按位异或(XOR)操作,而不是乘方操作。

表达式 9^2 表示对数字 9 和数字 2 进行按位异或操作。按位异或操作会对两个操作数的二进制表示进行逐位比较,如果相应位上的值不同,则结果为 1,否则为 0。

对于数字 9(二进制表示为 1001)和数字 2(二进制表示为 0010),按位异或的结果是 1011,即 11 的二进制表示。

因此,cout << 9^2 的输出结果是 11,而不是 81。

正确的表达式 cout << 9*9 << endl; 才能输出乘方的结果 81,即将数字 9 乘以自身。

因此,判断题的答案是错误的。cout << 9^2 << endl; 的输出结果是 11,而不是 81。

第 24 题 小杨今年春节回奶奶家了,奶奶家的数字电视要设置ip地址并接入到WIFI盒子才能收看节目,那这个WIFI盒子具有路由器的功能。( )

答案:正确

第 25 题 任何一个 for 循环都可以转化为等价的 while 循环( )。

答案:正确

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

第 26 题 相似字符串

第 27 题 做题