GESP C++一级易错点:运算符优先级、输入输出与循环边界
简介这是一份面向GESP C一级考生及少儿编程教师的2024年3月真题文档适合考前自测、课堂讲评与基础语法查漏补缺对初学者巩固语法、教师组织模拟测评也较实用。压缩包共1个docx文件约133KB采用可编辑试卷排版便于打印、批注和二次整理。内容覆盖表达式运算、输入输出、条件分支、循环结构、数组累加、类型转换、编译流程、操作系统与计算机常识等一级考点包含15道单选题、10道判断题以及“小杨买书”“找因数”两道编程题能帮助读者熟悉题型分布、分值结构与命题难度。目前已有1538人学习下载具备一定参考热度。借助完整题干与答案页读者可按选择、判断、编程三个模块分块练习对照错题定位薄弱知识点并围绕取模、循环累加、因数判断等常见写法进行针对性复习形成较系统的备考路径。1. 知识地图GESP C 一级真正考的是细节精度GESP C 一级的卷面结构相当固定15 道单选、10 道判断、2 道编程题两道编程题各 25 分、合计 50 分客观题与上机题基本对半分。很多人以为一级就是背语法真正拉开差距的是细节精度——一个空格、一次边界、一种类型转换。信奥赛这条路上一级是入门关卡它不考算法考的是你对 cin/cout、运算符优先级、for 与 while 的掌控是否真到位。这份笔记按「表达式 → 输入输出 → 分支循环 → 易错点 → 编程题」把整张卷子重排了一遍适合刚学完顺序、分支、循环三件套、准备第一次上考场的人。2. 表达式与运算符优先级、取模、类型转换三件套整张卷子里跟表达式相关的题目能占到客观题的三分之一。它们看起来最没技术含量实际上是失分重灾区因为选项往往只差一个字符或者一次隐式转换。把这一块拆成四件事谁先算、取模怎么算、类型怎么变、真假怎么判。2.1 运算符优先级括号是唯一不用背的东西卷面第一题就是(3 - 2) * 3 5。括号先算得 1乘 3 得 3加 5 得 8。这题本身不难难的是后面那些没有括号、全靠优先级和结合性说话的表达式。一级需要掌握的层级其实不多按从高到低排下来是括号、单目运算符!、-、、--、* / %、 -、关系运算 、相等判断 !、逻辑与、逻辑或||、赋值。优先级运算符结合方向一级常见考法1()从左到右强制改变计算顺序2!-负号--从右到左-a b先取负3*/%从左到右10 / 4 * 2得 4 不是 1.254-从左到右10 - 4 - 3得 35从左到右与算术混用时的顺序6!从左到右判断结果只有 0 和 17从左到右短路求值89从右到左a b 3真正需要背的只有一条同级运算符从左往右算。减法、除法、取模这三兄弟最容易被当成「可以随便换顺序」10 - 4 - 3从左算是 3先算右边就变成 9这种错误在笔试里几乎每年都有变体。#include iostream using namespace std; int main() { cout (3 - 2) * 3 5 endl; // 8括号 → 乘法 → 加法 cout 10 - 4 - 3 endl; // 3同级左结合先算 10-4 cout 10 / 4 * 2 endl; // 4先整除得 2再乘 2 cout 2 3 * 4 % 5 endl; // 4先 3*41212%52再加 2 return 0; }这几行输出的差异全部来自「先算谁」。第三行如果换成10 / (4 * 2)结果就是 1第四行如果把%换成-结果立刻变。考场上判断这类题稳妥做法是拿笔在表达式下面画分层线一层一层往下剥不要心算。2.2 取模运算%只认整数符号跟着被除数走第二题cout 5%2 5 % 2取模得 1前面那串字符串原样输出最终是5%21。取模的本质是求余数27 % 10得 7 这也是判断题第一题的原型。一级关于%的考点集中在三处只能用于整数、结果范围、负数怎么办。a % b的结果一定落在0到b-1之间a、b都为正时。这个性质是做数位分离题的基础比如n % 10拿个位、n / 10 % 10拿十位。负数取模在 C 里的规则是「向零取整余数符号与被除数一致」-7 % 3得-17 % -3得1。一级一般不深挖负数但判断题里会拿「取模结果一定小于除数」这种表述做文章。#include iostream using namespace std; int main() { int n 275; cout n % 10 endl; // 5个位 cout n / 10 % 10 endl; // 7十位先整除去掉个位 cout n % 100 endl; // 75末两位 cout -7 % 3 endl; // -1余数符号跟被除数 return 0; }注意n / 10 % 10的执行顺序/和%同级且左结合所以先整除再取模拿到的是十位而不是别的位。这个写法在真题里反复出现写反一次就会拿到个位而编译器一声不吭。2.3 类型与赋值3.0 和 3 值相等但不是一回事判断题第七题的原文是「3.0 和 3 的值相等所以它们占用的存储空间也相同」答案是错。3.0是double一般占 8 字节3是int一般占 4 字节。值相等和类型相同是两码事这是整张卷子里最容易被「常识」带偏的一题。选择题第十一题问哪个赋值语句不正确四个选项里x(3.16)、x3.16、xint(3.16)都能编过只有x3.16 int这种写法是语法错误——类型名不能跟在数值后面。这题真正想让你分清的是两件事int变量接收浮点数时会截断不是四舍五入以及强制类型转换的两种写法(int)3.16和int(3.16)都合法。#include iostream using namespace std; int main() { int x 3.99; // 截断为 3不是 4 double y 3; // 升级为 3.0占 8 字节 int z (int)3.99; // C 风格强转结果同样是 3 cout x y z endl; // 3 3 3 cout sizeof(x) sizeof(y) endl; // 4 8 return 0; }sizeof的具体字节数在不同平台上可能不同考试不会让你背死数字但「整型比浮点型占得少」这个方向必须清楚。另一个高频坑是int除法7 / 2得 3 而不是 3.5想要小数必须有一边是浮点型比如7 / 2.0。2.4 逻辑真假取模结果可以直接当条件用第八题里出现了if(i%3 i%7)这种写法没有写! 0。C 里非零即真i%3的结果是 0 就为假是 1 或 2 就为真。所以这个条件的含义是「i 既不能被 3 整除也不能被 7 整除」两个条件同时成立才累加。判断题第四题说10*2会报错理由是字符串和整数不能一起运算——这题对字符串字面量是const char[]跟整数相乘没有定义。和||还有短路特性A B里 A 为假就不再算 BA || B里 A 为真也不再算 B。一级不考带副作用的短路题但会让你判断「a 0 b / a 1这种写法安不安全」答案是因为短路a为 0 时右边根本不会执行。3. 输入输出cout、printf、cin、scanf 的四个坑第四题和第五题是同一段逻辑的两种写法输出却不一样这种题放在一起就是为了让你看清「看起来一样」和「真的一样」之间的距离。输入输出这一块一级的要求不高但极细拼接顺序、字符串里的空格、格式符、输入函数的职责边界每一项都能单独出一道题。3.1 cout 的拼接空格藏在字符串里不在运算符里第四题的代码是cout a1 a1 endl;注意等号后面那个空格它属于字符串的一部分。所以输出是a1 2等号和 2 之间有一个空格。第五题换成printf(a1%d\n, a1);格式串里等号后面直接跟%d输出就是a12没有空格。同一段计算逻辑输出差一个字符选项里四个答案就围着这个空格设。#include iostream #include cstdio using namespace std; int main() { int a 1; cout a1 a 1 endl; // a1 2等号后有一个空格 printf(a1%d\n, a 1); // a12等号后无空格 cout a1 a 1 endl; // a1 2效果同第一行 return 0; }三条语句的差别全在字符串常量里。判断这种题的方法很笨但有效把输出内容在草稿纸上逐字符抄一遍包括空格然后跟选项比对。抄的时候用竖线标出每个字符的位置比盯着看靠谱得多。3.2 printf 的格式串%d是占位符\n是换行判断题第二题printf(%d#%d,2,3)输出2#3两个%d依次被 2 和 3 替换#和是普通字符原样输出末尾没有\n所以不换行。printf的格式串里%d对应整型、%c对应字符、%f对应浮点、%%输出一个百分号本身\n是换行符而不是两个字符。一级常考的对比是「cout需不需要关心类型」cout会自动识别类型printf必须自己写对格式符写错了不会报错但会输出乱值。这也是为什么初学阶段更推荐cout但考试里两种都会出现必须都能读。3.3 cin 读入52读到第一个不合法字符就停第三题是这张卷子里设计得最巧的一道执行cin a时输入52会发生什么。四个选项里没有「a 等于 5」最终答案是「依赖于变量 a 的类型」因为如果a是intcin读到就停止a被赋值为 52留在缓冲区如果a是string整个52会被当成字符串读进去如果a压根没定义编译期就过不去。#include iostream using namespace std; int main() { int a 0; cin a; // 输入52 cout a endl; // 5遇到 停止读取 char op; cin op; // 接着从缓冲区读到 cout op endl; // return 0; }cin 的规则可以概括成跳过前导空白按目标类型读尽可能多的合法字符遇到不合法字符立刻停手并把该字符留在缓冲区。所以52不会报错也不会算出 7只会安静地给你一个 5。理解了这一点后面学字符串读入时那些「多读了一个换行」的玄学问题就都有了解释。3.4 编程题的输入输出规范多一个字就是零分两道编程题的题干里都有一句几乎一样的话由于系统限定请不要在输入输出中附带任何提示信息。这句话的分量比它看起来重得多。本地用 IDE 跑的时候cout 请输入金额这种提示语让人很舒服但评测机是拿你的输出跟标准答案逐字符比对的多一个汉字、多一个空行结果直接从满分变成零分。稳妥的输出习惯是只输出题目要求的内容每行末尾用endl或\n换行不要在最后多打一个空行也不要在两行结果之间插额外说明。写完之后把样例输入自己跑一遍把输出复制到记事本里打开「显示空格」对照样例逐字符看一眼。这个动作花不了一分钟能挡掉相当一部分翻车。4. 分支与循环执行次数、条件顺序与等价转换这一块是编程题的地基也是客观题里计算量最大的部分。真题里连着的四道题第六到第九题全在考「这段代码到底执行了几次、输出了什么」第十题则把循环用在质数判断上。核心能力只有一个能在脑子里把循环跑一遍并且跑对。4.1 if / else if命中一个就跳出整条链第六题输入 2121 % 3 0成立输出「能被3整除」然后整条else if链结束后面两个分支都不会执行。答案是「代码第 4 行被执行」。这题的错误选项集中在「第 4 行和第 7 行都执行」说明很多人把else if当成了两个独立的if。if / else if / else是一条互斥链从上往下依次判断谁先成立就执行谁执行完直接跳出。如果要让多个条件各自独立生效就得写成连续的if不加else。这两种写法在真题里都出现过判断的关键是有没有else。#include iostream using namespace std; int main() { int n 21; if (n % 3 0) cout 能被3整除 endl; // 命中后跳出整条链 else if (n % 7 0) cout 能被7整除 endl; // 不会执行 else cout 都不能 endl; // 不会执行 return 0; }如果把三个分支改成三个独立的if21 会同时满足「被 3 整除」和「被 7 整除」两行都输出。考场上遇到这类题先看有没有else再看条件的先后顺序最后才去算余数。4.2 for 循环执行次数两种数法互相验证第七题for(int i-10; i10; i)问循环体执行几次。第一种数法是「终点减起点」从 -10 到 9一共 20 个整数执行 20 次。第二种数法是「列首尾」-10、-9、…、0、…、9数一遍也是 20。两种方法对上了才敢落笔因为这类题错一个数就是全错。常见的边界错误有三种把当成多算一次从 0 开始时忘了 0 本身也算一次跨过 0 的区间按正数习惯算成 10 次。判断题第十题「任何 for 循环都能转成等价 while」是对的因为 for 的三个部分分别对应 while 的初始化、条件和迭代位置可以完全拆开。#include iostream using namespace std; int main() { for (int i -10; i 10; i) // i 取 -10 到 9共 20 个值 cout i ; cout endl; int j -10; // 等价的 while 写法 while (j 10) { cout j ; j; // 迭代语句挪到循环体末尾 } return 0; }两种写法输出完全一致。转换时唯一要留神的是continuefor 里的continue会跳到iwhile 里的continue会跳过循环体末尾的j一不小心就死循环。一级不考带continue的转换题但知道这个坑后面学循环控制会顺很多。4.3 循环体里的筛选与累加先翻译条件再动手算第八题的代码是遍历 0 到 9满足i%3 i%7就累加。把条件翻译成人话不能被 3 整除也不能被 7 整除。0 到 9 里符合的是 1、2、4、5、8加起来是 20。四个选项里 0、7、18、20 都有人选选 18 的通常是漏了 8 或者多算了 7。第九题更绕while(N)里先N - 1再判断N%3 0。N 从 10 开始减完是 9输出9#一路减到 3 输出3#再减到 0 时0 % 3 0成立输出0#然后while(0)退出。结果是9#6#3#0#。错选9#6#3#的人是把while(N)的判断时机记反了以为 0 不会进循环其实进循环的时候 N 还是 1。#include iostream using namespace std; int main() { int total 0; for (int i 0; i 10; i) if (i % 3 i % 7) // 非零即真两个余数都不为 0 total i; // 累加 1、2、4、5、8 cout total endl; // 20 return 0; }做这类题的统一动作是在草稿纸上画一列「i 的值 / 条件是否成立 / 累加后的结果」一边跑一边填。心算三五步还行超过五步必错。4.4 质数判断循环里最经典的一段填空第十题给出质数判断的骨架横线要填的是N % i 0。思路是用 1 到 N 之间的每个数去除 N统计能整除的次数次数恰好为 2只有 1 和它本身就是质数。填N % i得到的是余数非零为真逻辑正好反过来填N / i 0更离谱除法结果是商除非 N 小于 i 否则永远不为 0。这段代码虽然效率不高N 多大就循环多少次但一级的数据规模很小从 1 枚举到 N 完全够用。它同时也是「循环 分支 计数器」三件套的组合范例编程题里的找因数几乎是它的孪生兄弟。5. 易漏点清单五个最容易在考场上翻车的地方前面几章是按知识模块走的这一章换个角度按「错误类型」把整张卷子里最容易丢分的地方重新串一遍。每一条都按同一个套路写先说什么现象再说为什么会漏最后给一个可以立刻执行的动作。5.1 易漏点一空格和换行藏在字符串里眼睛看不见真题第四题和第五题的差别只有一个空格选项却围着它设了四个。这类题的共同特征是cout里的字符串常量、printf的格式串空白字符混在普通字符中间扫一眼根本分辨不出来。为什么会漏因为人读代码是「跳读」的大脑会自动把连续空白压缩成一个读中文时这个习惯帮我们省了很多力气读代码时就变成了系统性偏差。尤其是等号、冒号、逗号后面的空格最容易被当成排版而不是内容。怎么补养成「逐字符核对」的动笔习惯把输出内容抄在纸上用竖线分隔每个字符空格单独画一个小方格然后跟选项一处一处对。抄一遍花三十秒比反复看五遍管用。写程序时也有个笨办法输出前先在心里念一遍「这里有没有空格」念不出来的地方就加上显式分隔符。5.2 易漏点二值相等被当成类型相同判断题第七题说 3.0 和 3 值相等所以存储空间相同答案是错。类似的还有0和0、0和0值看着像类型完全不同。为什么会漏因为数学课上3.0 3是常识进了编程语境这层常识反而成了干扰。更深一层的原因是很多人学变量时只记住了「变量能存数」没建立「类型决定存储方式和运算规则」这个模型于是所有数字在脑子里都是同一类东西。怎么补把类型当成变量的一部分来记写int a的时候脑子里要出现「整数、4 字节、整除、取模可用」写double b的时候出现「小数、8 字节、有精度误差」。练习方式很简单遇到任何一个字面量先问自己三句它是什么类型、占多少空间、能不能参与取模。5.3 易漏点三循环边界差一多数一次或少算一次第七题从 -10 数到 9 是 20 次很多人第一反应是 21 或者 10。第九题的while里 0 会不会进循环也是同一类问题。为什么会漏因为 for 循环的三个部分里条件用的是还是只在开头出现一次后面全靠记忆。再加上负数、0、跨零区间这些不常见的起点平时的肌肉记忆直接失效。怎么补两个动作。第一写循环前先把首项和末项写在注释里比如// i 从 -10 到 9写完再对照条件检查一遍。第二用「小数据验证法」把上界改成 3 手动跑一遍看输出几个数对上了再换回原值。这个方法在纸面考试里同样适用在草稿纸上跑一个缩小版比硬算安全。5.4 易漏点四把输入函数和输出函数、提示函数搞混判断题第三题说scanf()的参数是字符串字面量、功能是提示输入答案是错。scanf是输入函数第一个参数是格式串不是提示语。第十二题问哪个语句能完成数据输入四个选项里只有scanf是输入printf和cout是输出default是switch里的标签跟输入输出毫无关系。为什么会漏因为初学阶段很多人是靠「背长相」记函数的scanf和printf长得像、都是标准库函数、都带格式串只差一个字母用的时候凭感觉挑一个。cin和cout同理in和out的区别在紧张时会被忽略。怎么补给每个函数配一句话的职责说明写在笔记最显眼的位置cin 从键盘读、cout 往屏幕写、scanf按格式读、printf按格式写。然后记一个判断口诀——「尖括号朝里的方向就是数据流动的方向」流进来流出去。5.5 易漏点五编程题输出多余提示语或多打空行两道编程题的题干都明确要求不要附带提示信息但每年仍然有人在这里丢分。表现有三种输出前加一句「请输入」、两行结果之间多一个空行、最后多一个换行。为什么会漏因为本地调试时提示语让程序好用而评测机的比对是逐字符的人眼看上去「一样」的输出在字节层面可能差好几个。更麻烦的是这种错误自己测不出来因为自己看自己的输出永远觉得对。怎么补交卷前做一次「纯净输出检查」把所有cout和printf里跟题目要求无关的字符串全部删掉只留数字和题目指定的符号然后把样例输入跑一遍复制输出粘贴到能显示空白字符的编辑器里跟样例输出逐行比对。这个习惯一旦养成后面所有线上评测都能少踩很多坑。6. 两道编程题拆解与考前复习清单两道编程题的分值加起来占一半但它们考的东西比客观题还基础。第一道是买书类问题一本书 13 元输入零用钱总额输出最多能买几本、还剩多少钱。本质就是一次整除加一次取模money / 13得本数money % 13得余数两行输出顺序不能反。#include iostream using namespace std; int main() { int money; cin money; // 零用钱总额 cout money / 13 endl; // 第一行本数整数除法自动向下取整 cout money % 13 endl; // 第二行剩余的钱 return 0; }第二道是找因数输入一个正整数 n从小到大输出它的所有因数每个一行。做法是从 1 枚举到 n能整除就输出天然有序不需要额外排序。一级的数据规模很小这个 O(n) 的写法完全够用不用去想平方根优化。#include iostream using namespace std; int main() { int n; cin n; for (int i 1; i n; i) { // 从 1 枚举到 n 本身 if (n % i 0) // 余数为 0 说明 i 是因数 cout i endl; // 每行一个顺序天然从小到大 } return 0; }这两道题合起来覆盖了一级编程题的全部套路读入一个整数、用整除取模或循环处理、按格式输出。考前把这两段代码默写一遍比刷十道选择题更稳。默写时重点检查三处cin后面有没有写、循环条件是还是、每行输出后面有没有换行。复习清单按「能不能独立复现」来定标准不按「看没看过」模块自检动作达标标准运算符优先级不查表写出23*4%5的结果30 秒内答出 4 并说清步骤取模与整除写出取n个位、十位的表达式一次写对n%10、n/10%10类型转换说出int x 3.99的结果答 3 并解释是截断不是四舍五入cout / printf写出带空格和不带空格的两种输出两种写法都不看资料cin 读入解释输入52后int变量的值答 5 并说明留在缓冲区分支判断if/else if链会执行几个分支答一个并说清互斥原因循环次数3 秒内算出for(i-10;i10;i)的次数答 20能说出两种数法编程题默写买书和找因数两段代码无提示、一次通过样例清单里任何一项做不到就回去翻对应的那一章不要跳着补。最后留一个我自己踩过的坑。早年做纸面题时我总觉得输出题的答案「差不多就行」空格多一个少一个无所谓直到有一次模拟测里连续三道输出题全错才发现问题不在会不会而在核不核对。从那以后我每次写完输出语句都会把样例输出贴在旁边用尺子比着逐字符看一遍包括行尾有没有多余空格。这个动作看起来傻但它救回来的分数比任何技巧都多。希望帮到你。本文还有配套的精品资源点击获取