GESP认证C++编程真题解析 | 202606 四级
附上汇总帖:GESP认证C++编程真题解析 | 汇总
单选题
第1题
小杨正在编写一个“数字交换器”程序,他希望通过函数交换两个变量的值。请问运行以下代码后,屏幕上输出的是( )。
voidexchange(int*a,int&b){intt=*a;*a=b;b=t;}intmain(){intx=100,y=200;exchange(&x,y);cout<<x<<" "<<y;return0;}A.100 200
B.200 100
C.200 200
D. 编译错误
【答案】:B
【解析】
函数exchange的第一个参数是 int指针,第二个参数是 int 引用,两种方式都能修改实参。调用exchange(&x, y) 时,a指向x,b是y的别名。执行t=a=100;a=b即x=200;b=t即y=100。所以交换后x=200,y=100,输出"200 100"。
第2题
下面程序想通过函数计算三门课总分,横线处应填入的是( )。
intsumScore(inta,intb,intc){returna+b+c;}intmain(){intchinese=88,math=95,english=90;inttotal=__________;cout<<total;return0;}A.sumScore
B.sumScore(chinese, math, english)
C.sumScore(int chinese, int math, int english)
D.sumScore(a, b, c)
【答案】:B
【解析】
调用函数时需要使用函数名加实参列表,实参的类型和顺序要与形参匹配。main p 函数中定义了chinese、math、english三个变量,应调用sumScore(chinese, math, english)。选项A缺少参数;选项C在调用时写了参数类型,这是函数声明语法而非调用语法;选项D使用的变量a、b、c在main中未定义。
第3题
下面程序输出结果是( )。
intaddOne(intx){returnx+1;}intmain(){inta=6;cout<<addOne(a)+addOne(3);return0;}A.9
B.10
C.11
D.12
【答案】:C
【解析】
addOne(a)=addOne(6)=7,addOne(3)=4,两者相加7+4=11。函数参数按值传递,在函数内部 x 是实参的副本,修改x不影响实参。
第4题
关于下面程序,说法正确的是( )。
voidshow(){intstars=5;}intmain(){cout<<stars;return0;}A. 程序输出5
B. 程序可以通过编译,但输出随机值
C. 程序不能通过编译,因为stars只在show函数中有效
D. 程序不能通过编译,因为cout不能输出变量
【答案】:C
【解析】
stars 是 show 函数内的局部变量,其作用域仅限于 show 函数的花括号内。在main函数中访问stars 会因变量未声明而编译失败。这体现了局部变量作用域的概念:局部变量在定义它的函数结束后就被销毁,外部无法访问。
第5题
小杨在调试一个“等级提升”系统,代码逻辑如下,执行后*p的值是( )。
intlv=5,next_lv=6;int*p=&lv;*p=*p+1;p=&next_lv;A.5
B.6
C.lv的地址
D.next_lv的地址
【答案】:B
【解析】
逐步分析:p=&lv,p指向lv;*p=*p+1即lv=5+1=6;然后p=&next_lv,p改为指向next_lv。此时*p=next_lv=6。注意最后一行只是改变了p的指向,并没有通过 p 修改 next_lv的值,所以*p的值就是next_lv的值6。
第6题
小杨正在开发一款名为“星际网格”的游戏,他用二维数组int map[5][4];来表示地图。已知int占 4 字节,如果map的内存地址是0x2000,则表达式&map + 1的地址值是( )。
A.0x204c
B.0x205c
C.0x2050
D.0x2058
【答案】:C
【解析】
&map是指向整个二维数组的指针,其类型是int(*)[5][4]。对&map加1,指针会跳过整个数组的大小。数组map共5×4=20个int,占20×4=80字节=0x50字节。所以 &map+1的地址=0x2000+0x50=0x2050。注意区分 map + 11(跳过一行16字节)和&map+1(跳过整个数组80字节)。
第7题
执行完下面代码后,变量val的值是( )。
intdata[]={10,20,30,40,50};int*ptr=data+2;intval=*(ptr-1)+*(ptr+1);A.50
B.60
C.70
D.80
【答案】:B
【解析】
data + 2指向data[2]=30。ptr-1指向data[1]=20,(ptr-1)=20;ptr+1 指向data[3]=40,(ptr +1)=40。val=20+40=60。指针的加减运算以元素大小为单位,ptr+n表示向后移动n个元素。
第8题
某班 3 个小组、每组 4 名同学的分数存入下面的二维数组score,则score[1][2]的值是( )。
intscore[3][4]={{80,81,82,83},{90,91,92,93},{70,71,72,73}};A.81
B.90
C.92
D.72
【答案】:C
【解析】
二维数组score有3行4列,下标从0开始。score[1][2]表示第2行(下标1)第3列(下标2)的元素。第2行是{90, 91, 92, 93},第3个元素(下标2)是92。
第9题
小杨定义了一个结构体Hero来表示游戏角色,下面哪种初始化方式会由于语法错误导致编译失败?( )。
structHero{string name;inthp;};A.Hero h = {"Arthur", 100};
B.
Hero h;h.name="Arthur";h.hp=100;C.Hero h = new Hero{"Arthur", 100};
D.Hero *p = new Hero{"Arthur", 100};
【答案】:C
【解析】
选项A使用列表初始化,语法正确。选项B先默认构造再逐成员赋值,语法正确。选项D用 new动态创建结构体并返回指针赋给 Hero,语法正确。选项C的错误在于new返回的是 Hero 指针类型,而左边h 是Hero对象类型,类型不匹配导致编译失败。正确写法应该是Hero *p = new Hero{"Arthur", 100}或Hero h{"Arthur", 100}。
第10题
下面程序输出结果是( )。
structBook{string title;intpages;};intmain(){Book books[2]={{"Math",120},{"Science",150}};cout<<books[1].title;return0;}A.Math
B.Science
C.120
D.150
【答案】:B
【解析】
books是结构体数组,books[0]={“Math”, 120},books[1]={“Science”, 150}。books[1].title 即第二个元素的title 成员,值为"Science"。注意数组下标从0开始,books[1]是第二个元素。
第11题
小杨在对“能量晶石”按亮度进行排序。如果两块晶石亮度相同,他希望保持它们在原始序列中的相对顺序。下列关于排序算法稳定性的说法,错误的是( )。
A. 冒泡排序是稳定的,因为只有在左边比右边大时才交换。
B. 插入排序是稳定的,因为它将元素插入到相等元素的右侧。
C. 选择排序是稳定的,因为它每次选出最小元素放在前面。
D. 稳定性是指排序后相等元素的相对位置不发生改变。
【答案】:C
【解析】
稳定排序的定义是:对于相等的元素,排序后它们的相对顺序保持不变。冒泡排序在相邻元素比较时,只有前一个大于后一个才交换,相等时不交换,所以是稳定的,A正确。插入排序将元素插入到相等元素的右侧(遇到相等的就停在其后面),保持稳定性,B正确。D是稳定性的标准定义,正确。选择排序每次选最小元素与当前位置交换,这个跨越式交换可能改变相等元素的相对顺序,所以选择排序是不稳定的,C说它是稳定的是错误的。
第12题
小杨的机器人正在能量踏板上跳跃,踏板编号为 1,2,3,…。跳到第 n 块踏板的方案数满足递推式 f(n)=f(n-1)+f(n-2)。若 f(1)=1, f(2)=2,则运行以下代码计算jump(5)的结果是( )。
intjump(intn){if(n<=2)returnn;inta=1,b=2,c=0;for(inti=3;i<=n;i++){c=a+b;a=b;b=c;}returnc;}A.5
B.8
C.13
D.21
【答案】:B
【解析】
这是斐波那契式的递推:jump(1)=1,jump(2)=2,jump(n)=jump(n-1)+jump(n-2)。逐步计算:jump(3)=1+2=3,jump(4)=2+3=5,jump(5)=3+5=8。代码用三个变量a、b、c滚动计算,避免了递归的重复计算。
第13题
在“模拟实验室”程序中,为了防止除以 0 导致崩溃,小杨使用了异常处理机制。执行以下代码将输出( )。
try{intx=10,y=0;if(y==0)throw"Zero Error";cout<<x/y;}catch(inte){cout<<"Error Code: "<<e;}catch(constchar*msg){cout<<"Caught: "<<msg;}A.0
B.Error Code: 0
C.Caught: Zero Error
D. 程序直接崩溃
【答案】:C
【解析】
y == 0时执行 throw “Zero Error”,抛出的是 const char* 类型的字符串字面量。try 块后续代码不再执行。第一个catch 捕获int类型,不匹配;第二个 catch 捕获 const char* 类型,匹配成功,输出"Caught: Zero Error"。异常处理的关键是 throw 的类型与 catch的参数类型匹配。
第14题
下面代码使用某种排序算法,将数组中的元素按从小到大排序。这段代码使用的排序算法是( )。
voidmystery_sort(doublearr[],intn){for(inti=0;i<n-1;i++){intminPos=i;for(intj=i+1;j<n;j++){if(arr[j]<arr[minPos]){minPos=j;}}doubletemp=arr[i];arr[i]=arr[minPos];arr[minPos]=temp;}}A. 冒泡排序
B. 插入排序
C. 选择排序
D. 非典型排序
【答案】:C
【解析】
这段代码的典型特征是:外层循环每轮确定一个位置i,内层循环从i+1到n-1找最小元素的位置minPos,然后将最小元素与位置i的元素交换。这正是选择排序的核心思想——每轮选出未排序部分的最小值放到已排序部分的末尾。与冒泡排序的区别是不相邻交换而是跨越交换;与插入排序的区别是不逐个后移而是直接找最值。
第15题
小杨正在读取“冒险日志”文件quest.txt。若文件内容为Level 10,执行以下程序后输出为( )。
ifstreamfin("quest.txt");string s;intv;fin>>s>>v;cout<<s.length()*v;A.50
B.15
C.70
D.5
【答案】:A
【解析】
文件内容为"Level 10",fin >> s 读取第一个以空格分隔的词"Level",s.length()=5;fin>>v 读取整数10。输出5×10=50。注意>>运算符读取时会自动跳过空白字符并以空格作为分隔符。
判断题
第1题
运行以下程序后,变量a的值最终会变为20。
voidmodify(int*p){*p=*p+10;}intmain(){inta=10;modify(&a);return0;}A. 正确
B. 错误
【答案】:A
【解析】
modify函数接收a的地址,通过*p=*p+10将a的值修改为10+10=20。指针传参可以在函数内修改实参的值,这是指针的核心用途之一。
第2题
在 C++ 中,引用一旦初始化并绑定到某个变量后,可以通过赋值语句将其重新绑定到另一个变量。
A. 正确
B. 错误
【答案】:B
【解析】
引用的一个重要特性是"一经绑定,不可更改"。引用在初始化时绑定到一个变量后,后续所有对引用的赋值操作实际上都是修改被引用变量的值,而不是让引用指向新的变量。这与指针不同,指针可以重新指向其他变量。所以"可以通过赋值语句将其重新绑定到另一个变量"的说法是错误的。
第3题
下面程序可以正确计算并输出 3 名学生的平均成绩。
structStudent{intid;intscore;};intmain(){Student students[3]={{1,90},{2,80},{3,100}};intsum=0;for(inti=0;i<3;i++){sum+=students[i].score;}doubleaverage=sum/3.0;cout<<average<<endl;return0;}A. 正确
B. 错误
【答案】:A
【解析】
程序定义了结构体数组,每个元素包含id和score。循环累加3名学生的成绩:sum=90+80+100=270。然后计算平均值 average =270/3.0=90.0。注意这里除以3.0而非3,确保进行浮点除法,结果正确。
第4题
选择排序算法在寻找每一轮最小值时,如果遇到相等的元素不进行交换,则选择排序是一种稳定的排序算 法。
A. 正确
B. 错误
【答案】:B
【解析】
选择排序的不稳定性并非仅仅因为"遇到相等的元素进行交换"。即使在内层循环中遇到相等元素不更新 minPos (即 if (arr[j]< arr[minPos])用严格小于),选择排序仍然可能不稳定。原因是外层循环的交换操作:当最小元素与位置i的元素交换时,可能把位置上原有的元素交换到后面,如果这个元素与后面某个相等元素原本有先后关系,就会被打乱。例如序列[5a, 5b, 2],第一轮选出最小值2与5a交换,得到[2, 5b, 5a],5a和5b的相对顺序变了。所以选择排序本质上是不稳定的。
第5题
如果使用带flag的冒泡排序,且待排序数组一开始就是有序的,那么算法只需一轮扫描即可结束,时间复杂度为O ( n ) O(n)O(n)。
A. 正确
B. 错误
【答案】:A
【解析】
带flag 的冒泡排序在每轮扫描前将 flag 设为false,如果发生交换就设为 true。如果数组本身有序,第一轮扫描中所有相邻元素比较都不会触发交换,flag 保持 false,算法提前结束。只需一轮n-1次比较,时间复杂度为O(n),这是冒泡排序的最佳情况。
第6题
在 C++ 中定义二维数组并初始化时,可以省略第一维,但不能省略第二维。因此int a[][2] = {{1, 2}, {3, 4}};是合法的,而int a[][] = {{1, 2}, {3, 4}};是不合法的。
A. 正确
B. 错误
【答案】:A
【解析】
C++中二维数组初始化时,编译器可以根据初始化列表自动推断第一维(行数)的大小,所以可以省略第一维。但第二维(列数)必须明确指定,因为编译器需要知道每行的元素个数来正确排列内存布局。int a[][2]= {{1, 2},{3, 4}}合法,编译器推断为2行2列;int a[][] = {{1, 2},{3, 4}}缺少第二维信息,编译器无法确定每行元素个数,不合法。
第7题
下面代码的时间复杂度是O ( 2 n ) O(2^n)O(2n)。
intcnt=0;for(inti=1;i<=n;i++){for(intj=1;j<=i;j++){cnt++;}}A. 正确
B. 错误
【答案】:B
【解析】
该代码外层循环执行n次,内层循环次数随变化,总执行次数为1 + 2 + … + n = n ( n + 1 ) 2 1+2+…+n=\frac{n(n+1)}{2}1+2+…+n=2n(n+1),最高次项为n 2 n^2n2,因此时间复杂度为O ( n 2 ) O(n^2)O(n2),而非O ( 2 n ) O(2^n)O(2n)。题目中说时间复杂度是O ( 2 n ) O(2^n)O(2n)是错误的。
第8题
假设文件output.txt能正常打开,下面代码通过rdbuf将cout的输出重定向到了文件中。
ofstreamfout("output.txt");streambuf*old_buf=cout.rdbuf();cout.rdbuf(fout.rdbuf());cout<<"GESP Exam";cout.rdbuf(old_buf);A. 正确
B. 错误
【答案】:A
【解析】
rdbuf()用于获取或设置流的缓冲区指针。cout.rdbuf(fout.rdbuf()) 将 cout 的输出缓冲区重定向到文件输出流 fout 的缓冲区,此后所有 cout 的输出都会写入文件 output.txt 而非屏幕。最后 cout.rdbuf(old_buf) 恢复cout原来的缓冲区,后续输出重新回到屏幕。这是C++中输出重定向的标准做法。
第9题
小杨想通过下面程序给饭卡充值,程序会输出70。
voidrecharge(intmoney){money+=20;}intmain(){intcard=50;recharge(card);cout<<card;return0;}A. 正确
B. 错误
【答案】:B
【解析】
recharge函数的参数:money是按值传递的,函数内修改的是 money这个副本,不影响实参 card的值。调用recharge(card)后,card 仍然是50,不会变成70。要真正修改card,需要使用引用传参void recharge(int &money)或指针传参void recharge(int *money)。
第10题
下面代码可以通过编译。
inta[5];a++;A. 正确
B. 错误
【答案】:B
【解析】
数组名a是一个常量指针(指向数组首元素),其值不能被修改。a++ 试图对数组名进行自增操作,相当于修改常量指针的指向,这是不允许的。编译器会报错 “lvalue required as increment operand” 。虽然数组名在表达式中会退化为指向首元素的指针,但它不是可修改的左值。
编程题
题解:洛谷 B4557 [GESP202606 四级] 扫雷
题解:洛谷 B4558 [GESP202606 四级] 身高体重指数