GESP认证C++编程真题解析 | 202606 四级
附上汇总帖GESP认证C编程真题解析 | 汇总单选题第1题小杨正在编写一个“数字交换器”程序他希望通过函数交换两个变量的值。请问运行以下代码后屏幕上输出的是 。voidexchange(int*a,intb){intt*a;*ab;bt;}intmain(){intx100,y200;exchange(x,y);coutx y;return0;}A.100 200B.200 100C.200 200D. 编译错误【答案】B【解析】函数exchange的第一个参数是 int指针第二个参数是 int 引用两种方式都能修改实参。调用exchange(x, y) 时a指向xb是y的别名。执行ta100ab即x200bt即y100。所以交换后x200y100输出200 100。第2题下面程序想通过函数计算三门课总分横线处应填入的是 。intsumScore(inta,intb,intc){returnabc;}intmain(){intchinese88,math95,english90;inttotal__________;couttotal;return0;}A.sumScoreB.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在调用时写了参数类型这是函数声明语法而非调用语法选项使用的变量a、b、c在main中未定义。第3题下面程序输出结果是 。intaddOne(intx){returnx1;}intmain(){inta6;coutaddOne(a)addOne(3);return0;}A.9B.10C.11D.12【答案】C【解析】addOne(a)addOne(6)7addOne(3)4两者相加7411。函数参数按值传递在函数内部 x 是实参的副本修改x不影响实参。第4题关于下面程序说法正确的是 。voidshow(){intstars5;}intmain(){coutstars;return0;}A. 程序输出5B. 程序可以通过编译但输出随机值C. 程序不能通过编译因为stars只在show函数中有效D. 程序不能通过编译因为cout不能输出变量【答案】C【解析】stars 是 show 函数内的局部变量其作用域仅限于 show 函数的花括号内。在main函数中访问stars 会因变量未声明而编译失败。这体现了局部变量作用域的概念局部变量在定义它的函数结束后就被销毁外部无法访问。第5题小杨在调试一个“等级提升”系统代码逻辑如下执行后*p的值是 。intlv5,next_lv6;int*plv;*p*p1;pnext_lv;A.5B.6C.lv的地址D.next_lv的地址【答案】B【解析】逐步分析plvp指向lv*p*p1即lv516然后pnext_lvp改为指向next_lv。此时*pnext_lv6。注意最后一行只是改变了p的指向并没有通过 p 修改 next_lv的值所以*p的值就是next_lv的值6。第6题小杨正在开发一款名为“星际网格”的游戏他用二维数组int map[5][4];来表示地图。已知int占 4 字节如果map的内存地址是0x2000则表达式map 1的地址值是 。A.0x204cB.0x205cC.0x2050D.0x2058【答案】C【解析】map是指向整个二维数组的指针其类型是int(*)[5][4]。对map加1指针会跳过整个数组的大小。数组map共5×420个int占20×480字节0x50字节。所以 map1的地址0x20000x500x2050。注意区分 map 11跳过一行16字节和map1跳过整个数组80字节。第7题执行完下面代码后变量val的值是 。intdata[]{10,20,30,40,50};int*ptrdata2;intval*(ptr-1)*(ptr1);A.50B.60C.70D.80【答案】B【解析】data 2指向data[2]30。ptr-1指向data[1]20(ptr-1)20ptr1 指向data[3]40(ptr 1)40。val204060。指针的加减运算以元素大小为单位ptrn表示向后移动n个元素。第8题某班 3 个小组、每组 4 名同学的分数存入下面的二维数组score则score[1][2]的值是 。intscore[3][4]{{80,81,82,83},{90,91,92,93},{70,71,72,73}};A.81B.90C.92D.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.nameArthur;h.hp100;C.Hero h new Hero{Arthur, 100};D.Hero *p new Hero{Arthur, 100};【答案】C【解析】选项A使用列表初始化语法正确。选项先默认构造再逐成员赋值语法正确。选项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}};coutbooks[1].title;return0;}A.MathB.ScienceC.120D.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正确。插入排序将元素插入到相等元素的右侧遇到相等的就停在其后面保持稳定性正确。是稳定性的标准定义正确。选择排序每次选最小元素与当前位置交换这个跨越式交换可能改变相等元素的相对顺序所以选择排序是不稳定的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(n2)returnn;inta1,b2,c0;for(inti3;in;i){cab;ab;bc;}returnc;}A.5B.8C.13D.21【答案】B【解析】这是斐波那契式的递推jump(1)1jump(2)2jump(n)jump(n-1)jump(n-2)。逐步计算jump(3)123jump(4)235jump(5)358。代码用三个变量a、b、c滚动计算避免了递归的重复计算。第13题在“模拟实验室”程序中为了防止除以 0 导致崩溃小杨使用了异常处理机制。执行以下代码将输出 。try{intx10,y0;if(y0)throwZero Error;coutx/y;}catch(inte){coutError Code: e;}catch(constchar*msg){coutCaught: msg;}A.0B.Error Code: 0C.Caught: Zero ErrorD. 程序直接崩溃【答案】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(inti0;in-1;i){intminPosi;for(intji1;jn;j){if(arr[j]arr[minPos]){minPosj;}}doubletemparr[i];arr[i]arr[minPos];arr[minPos]temp;}}A. 冒泡排序B. 插入排序C. 选择排序D. 非典型排序【答案】C【解析】这段代码的典型特征是外层循环每轮确定一个位置i内层循环从i1到n-1找最小元素的位置minPos然后将最小元素与位置i的元素交换。这正是选择排序的核心思想——每轮选出未排序部分的最小值放到已排序部分的末尾。与冒泡排序的区别是不相邻交换而是跨越交换与插入排序的区别是不逐个后移而是直接找最值。第15题小杨正在读取“冒险日志”文件quest.txt。若文件内容为Level 10执行以下程序后输出为 。ifstreamfin(quest.txt);string s;intv;finsv;couts.length()*v;A.50B.15C.70D.5【答案】A【解析】文件内容为Level 10fin s 读取第一个以空格分隔的词Levels.length()5finv 读取整数10。输出5×1050。注意运算符读取时会自动跳过空白字符并以空格作为分隔符。判断题第1题运行以下程序后变量a的值最终会变为20。voidmodify(int*p){*p*p10;}intmain(){inta10;modify(a);return0;}A. 正确B. 错误【答案】A【解析】modify函数接收a的地址通过*p*p10将a的值修改为101020。指针传参可以在函数内修改实参的值这是指针的核心用途之一。第2题在 C 中引用一旦初始化并绑定到某个变量后可以通过赋值语句将其重新绑定到另一个变量。A. 正确B. 错误【答案】B【解析】引用的一个重要特性是一经绑定不可更改。引用在初始化时绑定到一个变量后后续所有对引用的赋值操作实际上都是修改被引用变量的值而不是让引用指向新的变量。这与指针不同指针可以重新指向其他变量。所以可以通过赋值语句将其重新绑定到另一个变量的说法是错误的。第3题下面程序可以正确计算并输出 3 名学生的平均成绩。structStudent{intid;intscore;};intmain(){Student students[3]{{1,90},{2,80},{3,100}};intsum0;for(inti0;i3;i){sumstudents[i].score;}doubleaveragesum/3.0;coutaverageendl;return0;}A. 正确B. 错误【答案】A【解析】程序定义了结构体数组每个元素包含id和score。循环累加3名学生的成绩sum9080100270。然后计算平均值 average 270/3.090.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)。intcnt0;for(inti1;in;i){for(intj1;ji;j){cnt;}}A. 正确B. 错误【答案】B【解析】该代码外层循环执行n次内层循环次数随变化总执行次数为1 2 … n n ( n 1 ) 2 12…n\frac{n(n1)}{2}12…n2n(n1)最高次项为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_bufcout.rdbuf();cout.rdbuf(fout.rdbuf());coutGESP 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){money20;}intmain(){intcard50;recharge(card);coutcard;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 四级] 身高体重指数