简介:面向准备GESP C++一级认证的青少年考生、信奥赛入门学习者及编程教师,提供2023年9月认证真题,用于熟悉题型、考前自测与考点查漏补缺。压缩包内共1个docx文件,约147KB,内容为试卷文本,包含单选题、判断题和编程题,并附题目选项、编程题描述与样例说明,便于直接打印或改编练习。已有903人学习,适合作为一级考试的基础训练材料。试卷覆盖变量命名、逻辑与算术运算符、循环与数组处理、字符运算、类型转换等知识点;两道编程题“买文具”“小明的幸运数”可训练输入输出、条件判断、枚举与求和思路,帮助读者建立C++一级知识框架并提升答题熟练度。
1. 一张地图看清 GESP C++ 一级:从真题倒推复习重点
GESP C++ 一级这份 2023 年 9 月真题,题型结构本身就能说明考察重点:单选 15 题共 30 分、判断 10 题共 20 分、编程 2 题共 50 分,满分 100 分。前两类合计 50 分全部落在“概念加语法细节”上,后 50 分则要求把变量、输入输出、循环、条件判断串成能跑通的完整程序。也就是说,一级考查的项目并不在于算法有多难,关键看基本功是否扎实:能不能认出存储设备、能不能判断一个变量名合法、能不能算清&&和%的优先级、能不能写对for循环的边界。
适合谁看:刚接触 C++ 不久、准备第一次参加等级认证的人;学过一阵子但总在“看起来会、一做就错”的细节上丢分的人;以及带初学者、需要一份错题地图的人。这道题的风格很统一,几乎每个选项都在等你踩一个经典坑,比如字符相加、逗号表达式、cout到底算不算关键字。把这张地图记住,复习就不会东一榔头西一棒子。
2. 计算机常识与变量基础:送分题里的隐藏门槛
2.1 内存、存储设备与早期计算机常识
真题第一题问“我们通常说的内存属于计算机中的什么”,答案是存储设备。这题很多人靠直觉选,但复习时最好把设备分类一次性理清,因为判断题第一题又绕回来了:早期计算机内存不够大,会把字库固化在包含只读存储器的扩展卡里插到主板上帮助处理汉字,这句话是正确的。
| 设备类别 | 典型例子 | 一级要记的点 |
|---|---|---|
| 输入设备 | 键盘、鼠标、扫描仪 | 数据进入计算机 |
| 输出设备 | 显示器、打印机 | 结果离开计算机 |
| 存储设备 | 内存、硬盘、U 盘、ROM 扩展卡 | 内存属于这一类,不要选成输入输出 |
梳理下来会发现,这类题真正考的是“分类归属”,而不是让你解释内存的工作原理。内存是存储设备,不是“计算机的大脑”;CPU 才承担运算和控制。判断题里出现“只读存储器”时,要知道 ROM 属于存储器,扩展卡插在主板上是为了补足内存容量不足时存放字库的需求,方向判断为正确即可,不必深挖硬件细节。
另一道常识判断涉及超级计算机:题干描述一款国产超级计算机曾多次在全球榜单中名列前茅,这类表述按常理判断为正确。复习时不必背具体名称和排名,重点在于分清“常识判断”与“语法判断”——前者靠基本认知,后者靠规则记忆,两类别混。
2.2 变量命名规则与关键字辨析
变量命名是一级最稳定的考点。真题里redStar、RedStar、red_star、red star四个选项中,不合法的是red star,原因只有一个:中间有空格。
命名规则可以压缩成几条:
- 只能由字母、数字、下划线组成,不能有空格、
+、-、%这类符号; - 不能以数字开头,
2num不合法,num2合法; - 区分大小写,
redStar和RedStar是两个不同的名字; - 不能使用关键字,
int、for、while、return这类保留字不能当名字。
判断题里有一题说“不可以将变量命名为cout,因为cout是 C++ 的关键字”,这句话是错的。cout是标准库里的对象名,不是关键字,语法上你确实可以定义一个叫cout的变量,只是会和标准输出打架,属于“能编译但极易翻车”的写法。这道题的价值在于逼你区分“关键字”和“标准库标识符”,这也是很多人第一次意识到的事:编译器不拦你,不代表你可以这么干。
提示:复习关键字时按功能分组记,类型类(
int、char、double、bool)、控制类(if、else、for、while、do、switch、break、continue、return)、其他(const、void、true、false),比死背一张长表更牢。
2.3 数据类型与取整、类型转换
判断题第三题:int(3.14)的值为 3,正确。浮点数转整数是截断小数部分,不是四舍五入,int(3.99)同样是 3。这一点在编程题里会以更隐蔽的方式出现,比如算钱时用整数除法导致少算。
一级涉及的类型不多,但每种都要知道“能装什么”:
| 类型 | 存什么 | 一级易错点 |
|---|---|---|
int | 整数 | 除法/两边都是整数时结果取整,7 / 2得 3 |
double | 小数 | 不能对浮点数用%,c % 2.5直接语法错误 |
char | 单个字符 | '1'是字符,参与运算时用编码值 |
bool | 真/假 | 输出时默认是 1 和 0,不是 true/false |
b = c % 2.5;这道单选题考的就是取模运算只接受整数操作数,浮点数参与%不符合语法。很多人平时写代码没试过,考场上靠“好像可以”猜,就会错。复习方式很土但有效:把每个运算符允许的操作数类型写一遍,%只认整数,/看两边类型决定是整除还是小数除法。
3. 运算符与表达式:优先级、短路与逗号的连环坑
3.1 算术、关系、逻辑的优先级顺序
真题第 3 题:表达式2 - 1 && 2 % 10的值。拆解顺序是先算2 - 1得 1,再算2 % 10得 2,最后1 && 2,非零即真,结果是 1。答案选 B。
优先级从高到低,一级需要记牢的大致是:括号 →!→ 算术(* / %高于+ -)→ 关系(< > <= >=)→ 相等(== !=)→&&→||→ 赋值。这张顺序表不用背成顺口溜,但遇到复合表达式必须能一层层拆。
再看作比较的第 5 题,x = 2, y = 4, z = 6,判断哪个表达式为真:
| 选项 | 表达式 | 计算过程 | 结果 |
|---|---|---|---|
| A | x > y || x > z | 2>4假,2>6假 | 假 |
| B | x != z - y | z-y=2,2!=2 | 假 |
| C | z > y + x | y+x=6,6>6 | 假 |
| D | x < y || !x < z | 2<4真,短路后整体真 | 真 |
D 选项最容易看错,!x < z里!先作用于x,!2得 0,再0 < 6为真。但因为||左边已经是真,整个表达式直接短路为真。这里同时考了优先级和短路求值,属于一级选择题的典型复合考法。
3.2 短路求值与副作用
&&和||的短路规则必须形成条件反射:A && B中 A 为假就不再算 B;A || B中 A 为真就不再算 B。这条规则本身简单,坑在于“不算”意味着右边如果有赋值或自增,就不会发生。
int a = 0, b = 0; if (a != 0 && b++ > 0) { // 条件不成立,且 b++ 根本没有执行 } // 此时 b 仍然是 0,不是 1这段代码的意义在于说明:短路不仅影响结果,还影响副作用。一级选择题不会写得这么绕,但理解到这层,遇到“表达式值为多少”“变量最终是多少”这类题就不会慌。逻辑非!的优先级高于关系运算符,!x < z等价于(!x) < z,而不是!(x < z),这是另一个高频错点。
3.3 逗号表达式与 cout 输出
判断题第四题:cout << (2, 3, "23")的输出。括号里是逗号表达式,从左到右依次求值,整个表达式的值是最后一个,也就是字符串"23",所以输出是23,不是2,3,23。这道判断题的说法是错的。
逗号表达式的规则只有一条:从左往右算,取最右边的值。但它和cout的<<放一起就容易误读,因为<<的优先级高于逗号,没有括号时cout << 2, 3会被解析成(cout << 2), 3,先输出 2。有括号才是先算逗号表达式再输出。
#include <iostream> using namespace std; int main() { int b, c; // 逗号表达式:先赋值 b=3,再赋值 c=4,最后取 b+c int a = (b = 3, c = 4, b + c); cout << a << endl; // 输出 7,不是 3,也不是 4 return 0; }a拿到的是最后一个子表达式b + c的值,即 7,而b、c的赋值副作用照样发生。真题第 6 题里a = (b = 3, c = 4, b + c);被认为是合法语法,就是这个道理。同一题里a -= a = (b = 6) / (c = 2);也是合法的,虽然写法极不推荐,但它能编译,考的就是你能不能把“合法但不优雅”和“语法错误”分开。
3.4 复合赋值与自增自减
c += 5;等价于c = c + 5;,-=、*=、/=、%=同理。一级要掌握的关键点不是这些符号本身,而是“左边必须能接收值”——5 += c这种写法左边是常量,不合法。
自增自减在这个阶段先记两条:i++先用后加,++i先加后用;单独成句时两者没区别。真题里出现过在循环条件中写i += 2的判断题,说的是for (int i = 0; i < 10; i += 2)表示从 0 开始、到 10 结束但不含 10、间隔为 2,这个描述是正确的,循环变量依次取 0、2、4、6、8,共 5 次。
4. 流程控制:循环边界与字符运算的实战重点
4.1 for 循环的三段结构与边界判断
真题第 13 题求正整数的所有因数,输入 10 输出 1、2、5、10,输入 17 输出 1、17。要在横线处填循环头,正确答案是for (int i = 1; i < n + 1; i++)。四个选项的差别只有两处:上界是n还是n + 1,步进是i + 1还是i++。
这两处恰好是一级最经典的两个坑:
- 上界:求因数必须包含
n本身,因为任何正整数都能被自己整除。写i < n会漏掉n,输入 17 就只输出 1,直接错。 - 步进:
i + 1只是算了一个值,没有赋值回i,循环变量永远不变,直接死循环。
#include <iostream> using namespace std; int main() { int n; cin >> n; // i 从 1 遍历到 n(含 n),才能取到 n 这个因数 for (int i = 1; i <= n; i++) { if (n % i == 0) { cout << i << " "; } } return 0; }参数说明:i <= n与i < n + 1等价,前者更直观;n % i == 0判断整除关系,余数为 0 说明i是因数。这段代码也是编程题的基本骨架,后面两道大题都建立在同样的循环思路上。
4.2 while 与 do-while 的死循环辨析
判断题第七题说“do-while循环不可能导致死循环,但while有可能”,这是错的。两种循环都可能死循环,只要条件永远成立。do-while的特点是先执行一次再判断,因此即使一开始条件为假,循环体也至少跑一遍,这是它和while的核心差别。
判断题第八题涉及continue:如果循环体里continue无条件执行,会不会死循环?要看continue之前循环变量有没有推进。若推进语句被continue跳过,条件永远成立,就是死循环。这类题检验的是你能不能顺着执行流程走一遍,而不是背结论。
break与continue的分工要分清:break跳出整个循环,continue只跳过本次剩余部分、进入下一次。在一级的选择题里,经常用一段带if的循环让你数输出了几次,做法就是拿纸手动模拟,别在脑子里跑。
4.3 数位分解与取模运算
真题第 14 题要在横线处填写代码,使输出是正整数各位数字的平方和。横线处应填(n % 10) * (n % 10),因为n % 10取出最低位,平方后累加,再让n / 10去掉这一位,循环直到n变为 0。
#include <iostream> using namespace std; int main() { int n, sum = 0; cin >> n; while (n > 0) { int d = n % 10; // 取出当前最低位 sum += d * d; // 累加这一位的平方 n = n / 10; // 去掉最低位,整数除法自动截断 } cout << sum << endl; return 0; }这段是数位类题目的通用模板,两个动作必须成对出现:% 10取位、/ 10删位。只取不删会死循环,只删不取就漏算。变体包括求各位数字之和、求位数、反转数字,骨架完全一样,只换中间那行累加逻辑。
4.4 字符与 ASCII 编码
判断题第六题:('1' + '1')的值为'2',错误。字符'1'参与算术运算时用的是 ASCII 编码值,'1'是 49,相加得 98,对应字符'b',不是'2'。如果想让'1'变成数字 1,要写'1' - '0';想让数字变字符,写'0' + 1。
| 写法 | 结果 | 说明 |
|---|---|---|
'1' + '1' | 98 | 两个字符的编码相加 |
'1' - '0' | 1 | 字符转对应数字,常见套路 |
'0' + 1 | '1' | 数字转字符 |
int('1') | 49 | 显式取编码值 |
字符和整数之间的这层转换,是编程题输入的常见处理点。一级的输入多数直接给整数,用cin >> n就行,但一旦题目按字符读入,就必须知道'1'和1差着 48。
5. 编程题拆解:两道真题的完整思路与评分要点
5.1 买文具:条件判断与两种情况输出
第一道编程题是买文具:签字笔 2 元一支需 X 支,记事本 5 元一本需 Y 本,直尺 3 元一把需 Z 把,手里有 Q 元。总花费是2*X + 5*Y + 3*Z,与 Q 比较,够就输出Yes和剩余钱数,不够就输出No和缺少的钱数。
#include <iostream> using namespace std; int main() { int x, y, z, q; cin >> x >> y >> z >> q; // 四行输入,cin 连续读取即可 int cost = 2 * x + 5 * y + 3 * z; if (cost <= q) { cout << "Yes" << endl; cout << q - cost << endl; // 剩余 } else { cout << "No" << endl; cout << cost - q << endl; // 缺少 } return 0; }这段代码的评分点集中在几处:输出必须两行,第一行字符串大小写要与题面一致(Yes、No,不是YES);剩余和缺少的减法方向不能反,剩余是q - cost,缺少是cost - q;cin连续读四个变量默认以空白分隔,题目说输入四行,逐行读和一次读四个结果一样。
这道题最容易丢分的地方不是算法,而是输出格式。有人把两个数打到一行,有人把Yes写成YES,25 分直接打折。复习时养成习惯:写完先拿样例对一遍,肉眼比对每个字符。
5.2 小明的幸运数:枚举、整除与个位判断
第二道题定义“k 幸运数”:个位数为 k 的正整数,以及所有 k 的倍数。求 L 到 R 之间(含两端)所有 k 幸运数的和。范围是2 ≤ k ≤ 9、1 ≤ L ≤ R ≤ 1000,数据很小,直接枚举。
#include <iostream> using namespace std; int main() { int k, l, r, sum = 0; cin >> k >> l >> r; for (int i = l; i <= r; i++) { // 个位是 k,或者是 k 的倍数,满足其一即为幸运数 if (i % 10 == k || i % k == 0) { sum += i; } } cout << sum << endl; return 0; }关键参数:i % 10 == k判断个位数,注意k的范围是 2 到 9,所以不用担心k是两位数;i % k == 0判断倍数;两个条件用||连接,因为题目定义是“以及”,满足一个就算。样例验证:k=7、L=1、R=10,只有 7 同时是个位为 7 且是 7 的倍数,和为 7;k=7、L=10、R=20,14 是倍数、17 个位为 7,和 31,与题面一致。
最容易错的是把“以及”理解成“并且”,写成&&,结果一个数都不满足,输出 0。另一个坑是循环边界写成i < r,漏掉右端点 R。这两处和前面第 13 题的因数边界是同一个思维习惯问题:题目说“包括 L 和 R”,就必须<=。
6. 易漏点清单:五个最容易在考场上翻车的地方
易漏点一:字符与数字混用。为什么漏:平时写代码多用整数输入,很少碰字符运算,一看到'1' + '1'就顺着直觉答'2'。怎么补:把'1' - '0'这个转换套路写进笔记,遇到字符参与算术,先在旁边标出 ASCII 值再算。
易漏点二:循环上界要不要带等号。为什么漏:<和<=只差一个字符,读题时注意力都在循环体上。怎么补:凡题目出现“包括”“所有”“到 n 为止”,一律先确认右端点是否要取到,求因数、求区间和这两类题固定用<=。
易漏点三:&&和||在自然语言里的对应。为什么漏:中文“以及”在口语里有时表示并列递进,容易读成“并且”。怎么补:题目说“以及”“或者”时翻译成||,说“同时”“既……又……”时翻译成&&,写完拿一个边界样例验一验。
易漏点四:cout不是关键字、逗号表达式取最后一个值。为什么漏:这两条都属于“看起来像常识、实际靠背”的规则,没做过题就不会主动想。怎么补:把关键字表和标准库常用名(cout、cin、endl)分开列,逗号表达式单独记一句“从左到右算,取最右”。
易漏点五:输出格式与减法方向。为什么漏:思路对了就急着交,没逐字对样例,Yes/No大小写、两行输出、q - cost还是cost - q全在细节里。怎么补:每道编程题写完,强制用题目给的每组样例手跑一遍,输出逐字符比对,包括空格和换行。
注意:这五条都不是“不会”,而是“会但没注意”。一级的分数差距,基本就藏在这种地方。复习时把错题按这五类归档,比按题号归档有用得多。
7. 复习落地:一套可执行的查漏补缺流程
复习这件事,光看知识点不够,得有一个能反复走、每次都能暴露问题的流程。我自己的做法是把一级拆成三轮,每轮目标不同。
第一轮过规则,用一张自检表把“记忆型考点”扫一遍。下面这张表可以直接抄下来,每格打勾才算过:
| 检查项 | 自检问题 | 过关标准 |
|---|---|---|
| 设备分类 | 内存属于哪类设备 | 能立刻答存储设备 |
| 命名规则 | 哪四类名字不合法 | 空格、数字开头、符号、关键字 |
| 优先级 | 2-1&&2%10怎么算 | 能拆成三步说出结果 1 |
| 短路 | a!=0 && b++后 b 是多少 | 答 0,并解释原因 |
| 逗号表达式 | (2,3,"23")输出什么 | 答 23 |
| 字符运算 | '1'+'1'等于多少 | 答 98,不是'2' |
| 循环边界 | 求因数 i 到哪停 | i <= n |
| 数位分解 | 取位和删位分别用什么 | % 10和/ 10 |
第二轮过代码,把两道编程题的模板默写一遍,不看答案。买文具考的是顺序结构和条件分支,幸运数考的是循环加条件组合,两个模板覆盖了一级编程题的全部结构。默写时故意改一下边界,比如把i <= r改成i < r,看样例会不会挂,用这种方式确认自己真的理解边界。
第三轮过错题,按第 6 章那五类归档重做。每道错题旁边写一句“我当时为什么选错”,比如“以为 cout 是关键字”“把以及当成并且”。这句话比正确答案有用,因为下次遇到同类题,你想起的是自己当时的错误念头,而不是一个抽象规则。
// 通用自检骨架:任何一道编程题写完,套这个结构快速验边界 int main() { // 1. 读入:数量、范围、单位是否和题面一致 // 2. 计算:表达式顺序、整除还是小数、有没有漏乘 // 3. 分支:条件方向对不对,两种情况是否都覆盖 // 4. 输出:字符串大小写、行数、减法方向 return 0; }这套流程走完,大概能覆盖一级 90% 以上的失分点。剩下的那部分,多半是读题时漏了“正整数”“包括”这类限定词,属于习惯问题,只能靠每次读题时拿笔圈关键词。
我自己的血泪经验是:第一次做这类卷子,知识点全会,分数却不高,问题全出在“以为自己对”。从那以后我每次复习都强制走一遍上面那张自检表,哪怕觉得没必要也走,因为翻车从来不是因为不会,而是因为没检查。希望帮到你。
本文还有配套的精品资源,点击获取