ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C++期末复习指南:题型拆解、高频考点与答题技巧

C++期末复习指南:题型拆解、高频考点与答题技巧

简介:面向广州大学计算机课程的C++习题答案资料,围绕变量与数据类型、运算符与表达式、控制结构、函数、数组与指针等基础知识点展开,既适合校内学生课后巩固与考前复习,也适合C++初学者作为刷题参考。压缩包共包含1个doc文档,大小约1.55MB,文档以选择题及解答为主,并补充了将数学表达式改写为C++算术表达式、用逻辑表达式表示条件等操作题,内容集中便于按需查阅。目前已有442人学习下载。题目解析涵盖合法标识符、八进制与十六进制常量表示、浮点数据写法、运算符优先级、自增自减组合表达式(如i+++j、++i+j)、逻辑短路求值、条件表达式及逗号表达式等高频考点,也有指针与引用交换变量等经典问题,能帮助使用者通过典型习题加深对C++基础概念的理解,排查常见易错点。每道题除给出正确选项外还包含简要解答,遇到相似题目时可举一反三,尤其适合期末冲刺阶段快速过一遍常考题型。

1. 计算机C++答案怎么拿高分:先看懂考卷的三种题型和四大模块

刷完选择题你会发现,C++期末卷最难的题从来不是编程题,而是每个选项都“看着都对”的选择题。比如int i=1,j=2;问i+++j的值,三个常见答案3、4、5摆在面前,选错的人比选对的人多。这份计算机C++答案按期末卷原题顺序拆了四件事:基本概念与数据类型、运算符与表达式、控制结构、指针与引用。题型对应三种:选择题、程序阅读题、编程题,分值大概五三二开。选择题靠排除法拿分,阅读题靠手推变量变化表拿分,编程题靠模板保底。期末冲刺、补考复习、考研复试机试前想快速过一遍C++考点的人,都可以直接按这个顺序刷。

2. 基本概念与数据类型:选择题前12题的高频考点与简答模板

2.1 关键字、标识符与常量格式:背下一张表就能拿下6道题

这个模块在卷面上的位置是选择题第1到第12题。看似零散,实际只考四件事:程序结构、编译过程、语法符号、常量格式。main函数是唯一入口,源程序变目标程序必须经过编译,简单语句以分号结尾,这三个“常识”每年都会换着选项考。关键字考的其实不是背诵,而是区分大小写和“长得像”。IF不是关键字,go不是,integer也不是;sizeof、case、extern才是。判断时先看是不是全小写英文词,再看是不是C++语法里确实存在的词。

常量格式是一张表的事,直接对照记:

常量类型合法示例非法示例判断要点
十进制整数123无数字直接书写
八进制整数015080、0a0以0开头,只能含0到7
十六进制整数0x11、0xaf、0x1f0xg以0x开头,不能出现非法字母
浮点数12.34、-1e+5、0.1E-12-1e3.5、e-5、5.0e(1+4)e的前后必须符合指数格式
字符常量'a'、'\101''name'、a单引号内一个字符或转义序列

这张表直接对应选择题第9、10、11、12题。你只要记住三个判断点:整数前导符(0开头是八进制、0x开头是十六进制)、e后面必须跟整数、字符常量只能是一个字符或转义序列,这四道题的分数就到手了。'\101'是合法的字符常量,因为101是八进制转义,对应ASCII字符;'name'不合法,因为单引号里只能放一个字符;"a"是字符串不是字符。容易翻车的点是浮点数:-1e3.5错在e后面带了小数,e-5错在e前面没有数字,5.0e(1+4)错在指数不能是表达式。

2.2 类型、错误分类与“为什么需要类型”:简答题的标准答法

看一道几乎必出的选择题:有说明int a=0; double x=5.16;,以下哪一句属于编译错误?答案是a=a%x;。这类题的答题思路要从“运算符的操作数要求”出发:%要求两个操作数都是整型,a是int,x是double,类型不匹配在编译阶段就被拒绝,所以它是编译错误。x=a/x、x=x/a、x=x*a都能通过类型转换完成运算,属于合法语句。这道题表面考类型转换,实际考的是“运算符对操作数类型有硬性要求”,记住这个原则,类似题都不会错。

拿到这道题还要能回答一个追问:C++里的错误分几类?执行C++程序时出现的“溢出”错误属于运行错误,不是编译错误,也不是连接错误。逻辑错误的特征是程序能编译、能运行,但结果不对。把这三类分清楚,选择题第5题和综合题里的“找错题”就有固定答法:编译错误看语法和类型,运行错误看病态数据和处理,逻辑错误看算法和边界。答题时先说类别,再举一道对应症状,最后落到解决办法,这三点齐全就能拿全分。

这一章的思考题还有一个高频简答:什么叫数据类型?为什么变量必须声明类型?标准答法是:数据“类型”是对数据的抽象,类型相同的数据有相同的表示形式、存储格式和操作。定义一个变量时,计算机根据变量的类型分配存储空间,并以该类型解释存放的数据。答题时按“抽象定义→存储分配→操作解释”三步走,面试官想听的就是“类型决定了存储大小和解释方式”这一句。这个框架同样可以用来回答“普通变量和指针变量的区别”:普通变量存数据值,通过名访问;指针变量存地址值,通过间址访问对象。

阅读程序找输出也是这一章的常规题。如下这个程序,要求写出四行输出:

#include <iostream> using namespace std; int main() { int a = 1, b = 2; bool x, y; cout << (a++) + (++b) << endl; // (a++)取旧值1,(++b)先自增为3,结果4 cout << a % b << endl; // 此时a=2,b=3,2%3=2 x = !a > b; // !a为0,0>b(3)为假,x=0 y = a-- && b; // a--取旧值2为真,a变1,b为3为真,y=1 cout << x << endl; // 输出0 cout << y << endl; // 输出1 }

输出是四行:4、2、0、1。这里有两个得分点:a++是先用后加,++b是先加后用,第一行两个表达式叠加时,a取旧值1、b先变为3,所以结果是4不是5。第二个得分点是自增改变了a的当前值,a已经变成2,第二行a%b就是2%3。后两行一旦算错,多半是忘了自增改变了a的当前值。bool型输出是0或1,不要写成true或false。这类题的标准推进方式就是把每条语句执行后的变量值列出来,一个变量一行,自增立即更新,再往下算。

这一章还延伸出一个考点:数据对象在C++中有几种访问方式?答案是三种,名访问、引用(别名)访问、间址访问。名访问直接用变量名读写数据;引用访问通过引用名读写对象,效果和名访问一样;间址访问通过指针变量中存放的地址去访问对象。这三个术语在简答和阅读题里都出现过,答题时先给三种名称,再各写一行示例代码,就能覆盖所有得分点。

3. 运算符与表达式:优先级、自增自减、短路求值的得分套路

3.1 优先级与结合性:运算符优先级分层表怎么背最稳

优先级题在卷子上通常直接问“谁最高、谁最低”。这份答案里给出的是:在<=、*=、+、*四个选项中,*的优先级最高;在!、&&、!=、?:四个选项中,?:的优先级最低。这两道题其实是在考一张优先级总表,背法按层次记:

优先级(从高到低)运算符记忆点
1 单目!、++、--、*、&先处理单个操作数
2 算术*、/、% 然后 +、-乘除先于加减
3 关系<、<=、>、>=比较大小
4 相等==、!=判断相等
5 逻辑与&&两者为真
6 逻辑或||一者为真
7 条件?:三目运算
8 赋值=、+=、-=、*=最后执行
9 逗号,整个表达式最后

背的时候记口诀:单目算术关系逻辑条件赋值逗号。很多同学明明背了优先级还是翻车,是因为只看优先级不看结合性。结合性决定优先级相同的运算符从左到右还是从右到左算,赋值运算符是右结合,这一点在3.2和押题里还会再遇到。卷面上判断“谁高谁低”时,只能靠这张表,没有捷径。但写自己的代码时,不确定的优先级直接加括号,避免被读代码的人误解。

3.2 自增自减与短路求值:四道必考真题的推演

这是全卷选择题占比最高的考点。先看自增自减的四道经典题:

  • int i=1,j=2;表达式i+++j的值是3。解释:C++编译器把它解析成(i++)+j,取i自增前的旧值1加j的2,结果是3,计算后i变为2。
  • int i=1,j=2;表达式++i+j的值是4。解释:++i先把i变2,再加j等于4。
  • ++(a++)是错误的表达式。解释:a++的结果是临时值,不是左值,不能作为++的操作数。
  • a++++b是错误的表达式。解释:连续自增自减在语法上存在二义性,且a++不是左值,不能继续后置自增。

这四道题背后是同一个原理:前置自增返回自增后的对象,后置自增返回自增前的临时值。临时值不能再被赋值或自增,所以++(a++)和a++++b都会在编译期报错。答题时只要记得“后置自增的结果是右值”这一个结论,就能一次性排除所有类似选项。

短路求值是另一个高发考点。已知int i=0, j=1, k=2;逻辑表达式++i || --j && ++k的值是1。算这类题的顺序是:先按优先级看&&比||高,所以表达式等价于++i || (--j && ++k);运算时从左到右,++i先把i变成1,此时||左边为真,整个表达式立即确定为真,后面的--j和++k都不执行。所以j还是1,k还是2,式子结果是1。

再看它的变体:x=y=1; ++x || ++y;结束后x的值是2,y的值是1。原因完全相同:++x先把x变2,||左边为真,++y被短路。如果题目把||换成&&,y就会被执行,这是全年最容易丢分的一句。短路求值还有个连带的写法:! (y>=-100 && y<=-10) && ! (y>=10 && y<=100)这种复合条件,必须先算括号内,再算括号外的!,最后算中间的&&。看到逻辑表达式,先把括号优先级标出来,再判断有没有短路。

3.3 逻辑表达式翻译:区间、整除、闰年的三个标准写法

习题1.3的“用逻辑表达式表示条件”是填空题和编程题双料考点。最典型的是数学关系1<x<5:在C++里不能连写成1<x<5,因为它的求值顺序是(1<x)<5,1<x的结果是0或1,拿它再去和5比较,恒为真,表达不出区间含义。标准写法是1<x && x<5。这个错法几乎每届都有同学踩坑,原因在于数学连写和C++运算符的结合性不一致,读题时看到区间就下意识拆成两个比较,再用&&连接。

// 区间判断:1 <= x < 10 1 <= x && x < 10 // 整除判断:i被j整除 i % j == 0 // 闰年判断 (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)

这三行背下来,能解决一整道填空或编程题。闰年条件要按“能被4整除但不能被100整除,或者能被400整除”拆开,注意&&优先于||,所以括号可以省略,但建议写出来防止误读。答题时先写括号再判断,宁可多写括号,不要赌优先级。x、y中有一个小于z的写法是x<z || y<z,不是x<z && y<z,“有一个”对应或关系,语言关键词和逻辑运算符之间要同步。坐标点落在圆内的写法是sqrt(pow((x-10),2) + pow((y-20),2)) < 35,这条公式在编程题里出现过,用到的是数学库函数,pow和sqrt的参数顺序要写对。

4. 控制结构:if嵌套、switch穿透、循环次数的判断方法

4.1 if-else与switch:else配对、赋值陷阱与case穿透

选择结构里最阴险的坑是if(a=b)。题目给了一个程序:输入a为4、b为9,希望判断相等,结果却输出“9等于9”。原因是a=b是把b的值赋给a,赋值表达式的值就是b的值,也就是9,非0即真,所以走了if第一分支。这类题有一个固定答题步骤:看到判断表达式里有单个等号,先判定这是赋值,不是比较;再按“真值=被赋变量的值”分析;最后把=改成==。这个陷阱在C++期末卷里出现的频率极高,因为它能通过编译,不会报错,只会在逻辑上出错。

switch穿透是选择题和阅读题的另一大坑。原题:假设i=2,执行switch(i)的case 1到case 4,由于case 2没有break,会继续执行case 3的++i,遇到break才退出,i的值变成2。很多人选1,默认每个case自动跳出,实际上case只负责入口,不负责出口。拿到带switch的题,先把每个case的break圈出来,没有break就往下穿。如果有default,还要看default放在哪里,default不一定要放最后,但无论放哪里,都只在没有匹配的case时执行。

else配对规则也很常考:else总是和最近的、未配对的if结合。程序里嵌套很多层时,不要按缩进看配对,要按语法看位置。习题2.2第一题就是多层if-else if-else嵌套,缩进和实际配对不一致,正确结果是输出20。答题时从最内层开始,逐层向上找最近未配对的if,配对确定后再代入条件判断。

4.2 while、do-while与for:循环次数和死循环识别

三种循环的次数题,要根据“先判断还是后判断”来定。while和for先判断,条件不成立一次都不执行;do-while后判断,至少执行一次。原题有一道do-while:i=3时执行do{ i--; cout<<i; }while(i!=1);执行过程是第一次进循环输出2,判断2!=1成立,第二次进循环输出1,判断1!=1为假,结束,共执行2次。这题的易错点是数成3次,因为很多人把i!=1当成“不等于1就继续”,忘记了i已经变成1。

死循环识别题给的是一个do { ++k; } while(k>=0);,k初始0,执行一次变1,再判断1>=0永远成立,死循环。另一个样本for( i=0,j=5; i=j; )循环次数为5:i=j是赋值,不是判断,j从5依次减到0,前5次赋的值非0,条件为真,j变成0后赋值结果为0,条件为假,退出。这类题把每次循环结尾的条件值写出来,不会错。判断死循环就找循环条件里有没有可能变成假的路径,k>=0这种从1开始永远大于0的条件,一眼就能看出是死循环。

break和continue的分工也是阅读题高频考点:continue跳过本次循环剩余语句,进入下一次循环;break直接退出整个循环。习题2.2第三题用if(++i%3 != 1) continue; else cout<<i;输出4、7、10,因为continue把不满足条件的i跳过了,满足条件的走else输出。注意这里的++i是先加后取模,i从1开始,第一次判断时i已经变2,2%3=2不等于1,continue,i继续变3、4,直到i=4时4%3=1才输出。continue没有跳出循环,只是跳过了输出语句。

4.3 程序阅读题的整体推演:从变量表到输出结果

这一章有一道经典的综合阅读题:

int i = 0, j = 5; do { i++; j--; if (i > 3) break; } while (j > 0); cout << i << '\t' << j << endl;

按变量表推:第1轮结束i=1、j=4,i没到3,j>0成立;第2轮结束i=2、j=3,j>0成立;第3轮结束i=3、j=2,j>0成立;第4轮i=4、j=1,i>3触发break,直接退出,输出i=4、j=1。这道题同时考了do-while执行顺序和break的时机,读题时先在纸上画两列i和j,每轮更新一次,遇到break就停笔。do-while至少执行一次,所以不要从while条件开始推,要先走进循环体。

另一道嵌套循环的题特别容易算错:x=0; for(i=0;i<=3;i++){ x++; for(j=0;j<=3;j++){ if(j%2) continue; x++; } x++; }输出x=16。外层循环4轮,每轮x先加1,然后内层循环j为0到3,j为0和2时x各加1,j为1和3时被continue跳过,内层结束后x再加1,一轮就是4次加法,4轮共16。这种题的要点是:continue跳过的只是内层循环里被if(j%2)挡住的加法,不会跳出外层,缩进和花括号要看清楚。

5. 高频失分点:指针、引用与const的三类经典错法

5.1 *和&的五种身份:先记住这张对照表

指针和引用失分,大部分不是因为不会指针,而是因为同一个符号在不同位置含义不同。习题1.5第7题的阅读题把*和&的用法堆在一段程序里,很多同学看到*p = *p * *q就懵。其实这张对照表能解决所有身份判断:

出现位置符号含义
声明语句int *p*指针类型说明符
使用语句*p*间址访问符
使用语句*q*算术乘法运算符
声明语句int &ra&引用说明符
使用语句&a&取地址运算符

有了这张表,再看那段程序:int *p = &a, *q = &b;是声明指针并用地址初始化;*p = *p * *q;中首尾两个*是间址访问,中间一个是乘法;int * & rt = q;是从右往左读,rt是一个指针的引用,也就是q的别名。最后*rt = 30等价于*q = 30,把b改成30。整段程序输出 a=200、b=30、*p=200、*q=30、ra=200、*rt=30。这题能答对,指针符号这关就算过了。

这段程序的输入是a=10、b=20,先做*p = *p * *q,等价于a=10乘20等于200;再让ra=a,ra本来就是a的引用,这个操作没有改变值;最后*rt=30把b改成30。注意ra=a虽然写法上是赋值,但因为ra一直是a的别名,所以不改变a的200。这个细节也是失分点,很多人看到ra=a以为重新绑定引用,实际上引用不能重新绑定,只是赋值。

5.2 指针与引用题为什么错:五条错因逐条复盘

这里单独把五个最常错的点拿出来复盘,每条都按“错在哪、为什么错、怎么答对”来写。

错因一:混淆“指针变量的值”和“指针指向的值”。原题int i=10, *p=&i;问错误的叙述,很多人选“p的值为10”。p的值是变量i的地址,不是10;10是*p,也就是i的值。答题时只要看见“p的值为某个普通整数”,立刻警惕,正确答案通常就在这里。记住p、*p、&i三个符号的对应关系:p是地址,*p是内容,&i是取地址。

错因二:把整型值直接赋给指针。原题给int a=5, b=10, c; int *p1=&a, *p2=&b;,错误的赋值是p1 = a。a是int值,p1是int*,类型不匹配。注意*p2 = b是正确的,它把b的值赋给*p2指向的对象,也就是赋给b自己;p2 = p1是让两个指针指向同一个变量,也是合法的。答题时区分“赋值给指针”和“赋值给指针指向的对象”,前者要求右操作数是地址,后者要求类型匹配。

错因三:对引用重复绑定。原题int a=10, b; int &pa=a, &pb=b;,正确的是pb = pa。引用一旦初始化就不能重新绑定,所以&pb = a这种写法不合法;pb = &pa更是把地址值赋给int引用,类型就不对。在引用题里,看到执行语句里出现&引用名 = 某个值,基本可以判定是错误选项。引用初始化只能用对象名,不能用&变量。

错因四:引用交换变量时漏看别名。原题通过int &ra=a; int &rb=b;做三行交换:

int a = 5, b = 3, t; int &ra = a, &rb = b; t = ra; // t = 5,ra是a的别名 ra = rb; // a = 3,rb是b的别名 rb = t; // b = 5

结果a是3,b是5。这题选错的人是把引用当成独立变量,以为交换的是ra和rb两个“盒子”。实际上ra就是a,rb就是b,三行交换等价于t=a; a=b; b=t;。记住引用是别名,不是对象,所有对引用的操作都直接作用于原变量。

错因五:const的位置记反。const放在类型前,是“指向常量的指针”,指针本身可以改,指向的对象不能改;const放在*后,是指针常量,指针本身不能改,对象可以改。这份答案还总结了常引用写法const 类型 &引用名 = 对象名。答题时用一个口诀:const在前锁对象,在后锁指针。这个考点在思考题1.5第5题里专门归纳过,考前把四种形式写一遍,比反复看错题更有效。

6. 答题技巧与考前押题:排除法、手推法和编程题保底模板

6.1 选择题排除法与阅读题“变量变化表”手推法

选择题的作答顺序应该是:先看选项结构,再找可快速排除的选项。遇到“哪个是编译错误”,先用类型规则排除,%对整型有硬性要求,遇到double操作数立刻排除;遇到“哪个不能交换a和b”,逐个模拟三行代码,a=b; b=a;这种没有任何临时变量或加减法的选项,两步后a和b都变成原b,必然不能交换。排除法的核心是先找“类型不匹配”和“左值错误”两种硬伤,再考虑逻辑问题。

阅读题固定用手推法:纸上列出所有变量,每次语句执行后更新变量值,遇到||和&&做短路判断,遇到break和continue做标记。手推法最忌讳心算,卷面上留白足够,一行一行写,输出结果几乎不可能错。遇到自增自减,立即更新变量当前值,不要等整行表达式算完再更新,这样容易漏掉副作用。

6.2 三道押题与编程题保底模板

押题第一道是x += x -= x * x;,已知x=5,结果是-40。因为+=和-=是右结合,从右往左算:先x -= x*x,等价于x = 5 - 25 = -20,再x += -20,等价于x = -20 + (-20) = -40。这个组合每年都有,答题时写清楚两步,不要跳步。

押题第二道是条件表达式a<b ? a : c<d ? c : d,已知a=1、b=2、c=3、d=4,值为1。条件表达式右结合,语法上被解析为a<b ? a : (c<d ? c : d),但求值时先判断最左边的条件a<b,a<b成立,直接返回a=1,后面的c<d根本不会执行。很多人把右结合理解成“先算右边”,这是错的,右结合影响的是解析方式,不影响求值顺序。

押题第三道是逗号表达式(x=4*5, x*5), x+25,值是45。逗号表达式的值是最后一个子表达式的值,从左到右依次执行:先x=20,再求x*5=100,这个100是括号内逗号表达式的值,但整个大表达式还有后续,最后求x+25=45,作为整个表达式的值。答题时记住“取最后一项,从左到右算”,括号内的临时值不影响后续。

编程题背三个模板就能及格。第一个是三数交换排序:

int a, b, c, t; if (a > b) { t = a; a = b; b = t; } if (a > c) { t = a; a = c; c = t; } if (b > c) { t = b; b = c; c = t; }

这段代码通过三次两两比较,把最小值依次换到a和b的位置,最后c是最大值。注意每次交换后变量值都会更新,所以第二次和第三次比较用的一定是最新的值,不能从头再来一遍。第二个模板是三角形判断:先验证a+b>c && b+c>a && c+a>b,再判断等边、等腰、一般。第三个模板是百分制转五级分制:先判断输入范围,再用int(score)/10作为switch表达式,case 10和9输出a,8输出b,7输出c,6输出d,其余输出e。三个模板都能在习题2.4找到标准答案,考前默写一遍,比背一百个语法点更有效。从那以后,我每次做C++卷都强制自己先写变量变化表,再写代码,选择题先排除类型错误。这套流程帮我把指针题的得分率提了上来。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进