1 条题解
-
0
题意总结
- 需求背景:彼得的计算器损坏,需要编写一个新的计算器应用程序。该程序仅进行整数运算,支持加法、减法和乘法操作,能使用任意数量不超过50个字符的变量。
- 输入语法:输入遵循特定的EBNF语法规则,包括变量赋值(
var ":=" expression
)、打印变量值("PRINT" var
)、重置所有变量("RESET"
)等语句。表达式由项(term
)通过加减操作(addop
)组成,项由因子(factor
)通过乘操作(mulop
)组成,因子可以是括号内的表达式、变量或数字。变量名以字母开头,后跟最多49个字母或数字;数字可以带负号。输入中各部分之间可出现任意数量空格,每行少于200个字符。 - 变量未定义情况:变量尚未定义、引用了未定义的变量或定义中包含循环引用时,其值被视为未定义。
- 输出要求:对于每个“PRINT”语句,若变量已定义则输出其数值,若未定义则输出“UNDEF”。
解题思路总结
- 数据结构设计:
- 使用
map<string, string>
存储变量名及其对应表达式,方便查找和更新。 map<string, bool>
分别标记变量是否定义和是否在计算中被访问,用于处理变量状态和检测循环引用。map<char, int>
存储运算符优先级,辅助表达式计算。vector<string>
存储已定义变量名,便于重置操作。
- 使用
- 输入解析:逐行读取输入,去除空格和换行符,将输入拆分成代码片段存储在数组中,对字母、数字、赋值符号和运算符等进行处理。
- 命令处理:
- “RESET”命令:遍历已定义变量列表,将变量定义标记置为
false
,清空变量表达式,并清空变量列表。 - “PRINT”命令:检查变量是否定义,若未定义输出“UNDEF”;若已定义,标记访问状态,调用计算函数求值,若计算中出现错误(未定义变量或循环引用)输出“UNDEF”,否则输出结果,并重置访问标记。
- 变量赋值命令:检查变量是否定义,未定义则标记为已定义并添加到变量列表,存储变量名和表达式,若表达式以负号开头则添加前导0。
- “RESET”命令:遍历已定义变量列表,将变量定义标记置为
- 表达式计算:
- 计算函数使用两个栈分别存储数字和运算符,遍历表达式,根据字符类型(数字、字母、运算符和括号)进行相应处理。
- 数字转换为整数入栈;字母提取变量名,检查定义和访问状态,递归计算变量表达式值入栈;根据运算符优先级处理运算符和括号。
- 遍历完表达式后,处理运算符栈中剩余运算符,最终返回数字栈顶元素作为表达式值。
#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
- 上传者