1 条题解

  • 0
    @ 2025-4-9 22:26:29

    题意总结

    1. 需求背景:彼得的计算器损坏,需要编写一个新的计算器应用程序。该程序仅进行整数运算,支持加法、减法和乘法操作,能使用任意数量不超过50个字符的变量。
    2. 输入语法:输入遵循特定的EBNF语法规则,包括变量赋值(var ":=" expression)、打印变量值("PRINT" var)、重置所有变量("RESET")等语句。表达式由项(term)通过加减操作(addop)组成,项由因子(factor)通过乘操作(mulop)组成,因子可以是括号内的表达式、变量或数字。变量名以字母开头,后跟最多49个字母或数字;数字可以带负号。输入中各部分之间可出现任意数量空格,每行少于200个字符。
    3. 变量未定义情况:变量尚未定义、引用了未定义的变量或定义中包含循环引用时,其值被视为未定义。
    4. 输出要求:对于每个“PRINT”语句,若变量已定义则输出其数值,若未定义则输出“UNDEF”。

    解题思路总结

    1. 数据结构设计
      • 使用 map<string, string> 存储变量名及其对应表达式,方便查找和更新。
      • map<string, bool> 分别标记变量是否定义和是否在计算中被访问,用于处理变量状态和检测循环引用。
      • map<char, int> 存储运算符优先级,辅助表达式计算。
      • vector<string> 存储已定义变量名,便于重置操作。
    2. 输入解析:逐行读取输入,去除空格和换行符,将输入拆分成代码片段存储在数组中,对字母、数字、赋值符号和运算符等进行处理。
    3. 命令处理
      • “RESET”命令:遍历已定义变量列表,将变量定义标记置为 false,清空变量表达式,并清空变量列表。
      • “PRINT”命令:检查变量是否定义,若未定义输出“UNDEF”;若已定义,标记访问状态,调用计算函数求值,若计算中出现错误(未定义变量或循环引用)输出“UNDEF”,否则输出结果,并重置访问标记。
      • 变量赋值命令:检查变量是否定义,未定义则标记为已定义并添加到变量列表,存储变量名和表达式,若表达式以负号开头则添加前导0。
    4. 表达式计算
      • 计算函数使用两个栈分别存储数字和运算符,遍历表达式,根据字符类型(数字、字母、运算符和括号)进行相应处理。
      • 数字转换为整数入栈;字母提取变量名,检查定义和访问状态,递归计算变量表达式值入栈;根据运算符优先级处理运算符和括号。
      • 遍历完表达式后,处理运算符栈中剩余运算符,最终返回数字栈顶元素作为表达式值。
    #include <iostream>
    #include <string>
    #include <vector>
    #include <map>
    #include <stack>
    #include <cctype>
    using namespace std;
    
    bool flag;
    string s, code[1010];
    vector<string> var;
    map<char, int> piror;
    map<string, string> expressionData;
    map<string, bool> isdefined, vis;
    
    bool isletter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
    bool issymbol(char c) { return (c == '+' || c == '-' || c == '*' || c == '(' || c == ')'); }
    
    int calculator(string expre) {
      if (!flag) return 0;
      stack<int> num;
      stack<char> symbol;
      
      for (int i = 0; i < expre.length(); i++) {
          if (isdigit(expre[i])) {
              int x = 0;
              while (i < expre.length() && isdigit(expre[i])) {
                  x = x * 10 + expre[i] - '0';
                  i++;
              }
              i--;
              num.push(x);
          }
          else if (isletter(expre[i])) {
              string tmp;
              while (i < expre.length() && (isdigit(expre[i]) || isletter(expre[i]))) {
                  tmp += expre[i];
                  i++;
              }
              i--;
              if (!isdefined[tmp] || vis[tmp] == true) {
                  flag = false;
                  return 0;
              }
              vis[tmp] = true;
              num.push(calculator(expressionData[tmp]));
          }
          else if (issymbol(expre[i])) {
              if (symbol.empty()) symbol.push(expre[i]);
              else if (expre[i] == '(') symbol.push(expre[i]);
              else if (expre[i] == ')') {
                  while (!symbol.empty() && symbol.top() != '(') {
                      char c = symbol.top(); symbol.pop();
                      int b = num.top(); num.pop();
                      int a = num.top(); num.pop();
                      if (c == '+') num.push(a + b);
                      else if (c == '-') num.push(a - b);
                      else if (c == '*') num.push(a * b);
                  }
                  if (!symbol.empty()) symbol.pop();
              }
              else {
                  while (!symbol.empty() && piror[symbol.top()] >= piror[expre[i]]) {
                      char c = symbol.top(); symbol.pop();
                      int b = num.top(); num.pop();
                      int a = num.top(); num.pop();
                      if (c == '+') num.push(a + b);
                      else if (c == '-') num.push(a - b);
                      else if (c == '*') num.push(a * b);
                  }
                  symbol.push(expre[i]);
              }
          }
      }
      
      while (!symbol.empty()) {
          char c = symbol.top(); symbol.pop();
          int b = num.top(); num.pop();
          int a = num.top(); num.pop();
          if (c == '+') num.push(a + b);
          else if (c == '-') num.push(a - b);
          else if (c == '*') num.push(a * b);
      }
      
      return num.top();
    }
    
    int main() {
      piror['*'] = piror['/'] = 2;
      piror['+'] = piror['-'] = 1;
      piror['('] = 0;
      piror[')'] = 3;
      
      while (getline(cin, s)) {
          int cnt = 0;
          bool QWQ = true;
          
          for (int i = 0; i < s.length(); i++) {
              if (s[i] == ' ' || s[i] == '\n') continue;
              cnt++;
              
              if (isletter(s[i])) {
                  while (i < s.length() && (isdigit(s[i]) || isletter(s[i]))) {
                      code[cnt] += s[i];
                      i++;
                  }
                  if (QWQ == false) {
                      code[++cnt] += ")";
                      QWQ = true;
                  }
                  i--;
              }
              else if (isdigit(s[i])) {
                  while (i < s.length() && isdigit(s[i])) {
                      code[cnt] += s[i];
                      i++;
                  }
                  if (QWQ == false) {
                      code[++cnt] += ")";
                      QWQ = true;
                  }
                  i--;
              }
              else if (s[i] == ':') {
                  code[cnt] += ":=";
                  i++;
              }
              else if (issymbol(s[i])) {
                  if (issymbol(code[cnt - 1][0]) && code[cnt - 1] != ")" && code[cnt - 1] != "(" 
                      && s[i] != '(' && s[i] != ')') {
                      code[cnt++] += "("; 
                      code[cnt++] += "0";
                      QWQ = false;
                  }
                  code[cnt] += s[i];
              }
          }
          
          if (code[1] == "RESET") {
              for (int i = 0; i < var.size(); i++) {
                  isdefined[var[i]] = false;
                  expressionData[var[i]] = "";
              }
              var.clear();
          }
          else if (code[1] == "PRINT") {
              if (!isdefined[code[2]]) printf("UNDEF\n");
              else {
                  flag = true;
                  vis[code[2]] = true;
                  int ans = calculator(expressionData[code[2]]);
                  if (flag == false) printf("UNDEF\n");
                  else printf("%d\n", ans);
                  for (int i = 0; i < var.size(); i++) vis[var[i]] = false;
              }
          }
          else {
              if (!isdefined[code[1]]) {
                  isdefined[code[1]] = true;
                  var.push_back(code[1]);
              }
              expressionData[code[1]] = "";
              for (int i = 3; i <= cnt; i++) {
                  if (code[i] == ":=") continue;
                  expressionData[code[1]] += code[i];
              }
              if (expressionData[code[1]][0] == '-') 
                  expressionData[code[1]] = "0" + expressionData[code[1]];
          }
          
          for (int i = 1; i <= cnt; i++) code[i] = "";
      }
      
      return 0;
    }  
    
    • 1

    信息

    ID
    422
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者