【GESP】C++三级练习 luogu-P1597 语句解析-系列题目1
这是一道我正在带孩子进行练习的题,从题目本身的描述来看,是一个简单的字符串处理问题,应属于GESP三级,字符串相关内容(难度二级也可以做)。
但在一开始做题的过程中,我们对题目描述的理解存在一点模糊,比如:题目描述中没有说明变量的赋值顺序规则,比如a:=3;b:=c;c:=4
的结果应该是3 4 4
还是3 0 4
。且,我对a、b、c三个变量的理解还存在一点误会(我想复杂了)我以为是三个变量,变量名不确定。
也就是因为这些理解的偏差,我认为这道题可以进行很多的变形,是值得我们逐步深入练习的,接下来,我们将围绕此题,逐步变形,逐步提升难度,锻炼能力,一起开始吧😊。
luogu-P1597 语句解析
题目要求
题目描述
一串长度不超过 $255$ 的 PASCAL 语言代码,只有 $a,b,c$ 三个变量,而且只有赋值语句,赋值只能是一个一位的数字或一个变量,每条赋值语句的格式是
[变量]:=[变量或一位整数];
。未赋值的变量值为 $0$ 输出 $a,b,c$ 的值。
输入格式
一串符合语法的 PASCAL 语言,只有 $a,b,c$ 三个变量,而且只有赋值语句,赋值只能是一个一位的数字或一个变量,未赋值的变量值为 $0$。
输出格式
输出 $a,b,c$ 最终的值。
输入输出样例 #1
输入 #1
1
a:=3;b:=4;c:=5;
输出 #1
1
3 4 5
说明/提示
输入的 PASCAL 语言长度不超过 $255$。
题目分析
- 问题分析
这道题目主要考察字符串处理和变量赋值的实现:
- 输入是一串PASCAL语言代码,只包含a、b、c三个变量
- 只有赋值语句,格式固定为
[变量]:=[变量或一位整数];
- 变量未赋值时默认为0
- 需要按顺序输出a、b、c的最终值
- 核心算法
- 字符串解析
- 遍历输入字符串,识别赋值语句的各个部分
- 通过
:=
分隔变量名和赋值内容 - 使用
;
判断语句结束
- 变量处理
- 维护三个整型变量a、b、c记录当前值
- 赋值分两种情况:
- 数字赋值:直接将一位数字转换为整数赋值
- 变量赋值:将源变量的当前值赋给目标变量
- 实现要点
- 字符串遍历时需要正确处理各种分隔符
- 需要准确判断赋值内容的类型(数字还是变量)
- 保持变量值的实时更新
- 复杂度分析
- 时间复杂度:$O(n)$,其中n为输入字符串长度
- 空间复杂度:$O(1)$,只需要常数个变量存储
示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 引入输入输出流库,用于控制台输入输出
#include <iostream>
// 引入string库,用于字符串处理
#include <string>
// 引入字符处理库,用于isdigit等字符判断函数
#include <cctype>
int main() {
// 定义输入字符串变量
std::string str;
std::cin >> str;
// 初始化三个变量a,b,c的值为0
int a = 0, b = 0, c = 0;
// 用于存储当前正在处理的变量名
std::string v_name = "";
// 遍历输入字符串的每个字符
for (int i = 0; i < str.length(); i++) {
if (str[i] == '=') { // 遇到等号,开始处理赋值操作
if (isdigit(str[i + 1])) { // 如果等号后是数字
// 根据变量名将数字赋值给对应变量
if (v_name == "a") {
a = str[i + 1] - '0'; // 将数字赋值给变量a
} else if (v_name == "b") {
b = str[i + 1] - '0'; // 将数字赋值给变量b
} else {
c = str[i + 1] - '0'; // 将数字赋值给变量c
}
} else { // 如果等号后是变量
// 处理变量间的赋值
if (str[i + 1] == 'a') { // 将a的值赋给其他变量
if (v_name == "b") {
b = a; // 将变量a的值赋给变量b
}
if (v_name == "c") {
c = a; // 将变量a的值赋给变量c
}
} else if (str[i + 1] == 'b') { // 将b的值赋给其他变量
if (v_name == "a") {
a = b; // 将变量b的值赋给变量a
}
if (v_name == "c") {
c = b; // 将变量b的值赋给变量c
}
} else { // 将c的值赋给其他变量
if (v_name == "b") {
b = c; // 将变量c的值赋给变量b
}
if (v_name == "a") {
a = c; // 将变量c的值赋给变量a
}
}
}
i += 2; // 跳过等号和赋值内容
} else {
// 记录当前处理的变量名
if (str[i] != ':') {
v_name = str[i]; // 存储变量名(a、b或c)
} else {
continue; // 跳过冒号
}
}
}
// 按要求格式输出三个变量的最终值
std::cout << a << " " << b << " " << c;
return 0;
}
后续拓展
针对原题的代码解答已经完成了。但我认为,本题能学到的远远不止于此,因为题目本身对输入格式限制的比较多,比如:
- 只有a、b、c三个变量,且只有赋值语句
- 赋值语句的格式为
[变量]:=[变量或一位整数];
所以我们目前的实现方式是针对变量只有3个、变量名只有一位、变量值也只有一位
等特征,“写死”的一套解题代码。
但,如果我们逐步考虑输入格式的变化,比如:变量增加到多个、变量名不确定、变量值也增加到多位等情况,题目的难度就慢慢提升了,适合3-4级左右的孩子练习,且这种循序渐进、逐渐深入、挖深吃透的练习模式我认为对孩子的收益是最大的。
接下来,我和孩子正在尝试处理:
- 变量仍然只有3个
a
、b
、c
- 变量值可以是 多位整数(int范围内) 或者变量名
由于我们原代码的逻辑只针对变量值只有一位的整数的情况,因此我们需要修改原代码的部分逻辑,使其能够处理多位整数的情况。
显然,新代码应仍然能通过P1597原题的所有测试用例。有兴趣的同学可以尝试一下,后续我会继续更新我和孩子的学习成果。
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP各级别考纲、真题讲解、知识拓展和练习清单等详见【置顶】【GESP】C++ 认证学习资源汇总
“luogu-”系列题目可在洛谷进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助