文章

【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$。


题目分析

  1. 问题分析

这道题目主要考察字符串处理和变量赋值的实现:

  • 输入是一串PASCAL语言代码,只包含a、b、c三个变量
  • 只有赋值语句,格式固定为[变量]:=[变量或一位整数];
  • 变量未赋值时默认为0
  • 需要按顺序输出a、b、c的最终值
  1. 核心算法
  • 字符串解析
    • 遍历输入字符串,识别赋值语句的各个部分
    • 通过:=分隔变量名和赋值内容
    • 使用;判断语句结束
  • 变量处理
    • 维护三个整型变量a、b、c记录当前值
    • 赋值分两种情况:
      • 数字赋值:直接将一位数字转换为整数赋值
      • 变量赋值:将源变量的当前值赋给目标变量
  1. 实现要点
  • 字符串遍历时需要正确处理各种分隔符
  • 需要准确判断赋值内容的类型(数字还是变量)
  • 保持变量值的实时更新
  1. 复杂度分析
  • 时间复杂度:$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个abc
  • 变量值可以是 多位整数(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),考试认证学员交流,互帮互助

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
本文由作者按照 CC BY 4.0 进行授权