基础的数学运算
前言:本来打算做科学计算器的,但是看到B站已经有了现成的了。决定做Python(毕竟也算计算器)
本期实现:
- 加减乘除
- 括号分析
- 基础变量实现
- Python 输出样式
大量使用了堆的容器。没什么高的技术含量,主要是转化成后缀表达式(逆波兰表达式挺有含金量)
后缀表达式(逆波兰表达式)
v0.1源代码
#include
#include
#include
#include
#include
#include
#include
using namespace std;
stack operators;
stack temp_suffix_result;
unordered_map variables; // Global container for variables
typedef struct symbol
{
string name;
string data;
int typ;
int pri;
int pos;
double val;
} SYMBOL;
/*
移除字符串中的空格
*/
string remove_spaces(string *str)
{
str->erase(std::remove(str->begin(), str->end(), ' '), str->end());
return *str;
}
/*
优先级map
*/
std::unordered_map precedence = {
{'+', 1},
{'-', 1},
{'*', 2},
{'/', 2},
{'^', 3}};
/*
处理操作符
*/
void process_operator(char op, std::stack &operators, std::stack &temp_suffix_result)
{
while (!operators.empty() && operators.top() != "(" &&
precedence[operators.top()[0]] >= precedence[op])
{
temp_suffix_result.push(operators.top());
operators.pop();
}
operators.push(std::string(1, op));
}
/*
优化原始表达式,方便转化为逆波兰表达式
*/
void Expression_optimization(string *str)
{
std::regex pattern("\\*\\*"); // 正则表达式中需要转义的字符
std::string replacement = "^";
// 使用 std::regex_replace 进行替换
*str = std::regex_replace(*str, pattern, replacement);
/*在单独的负数,负号前面插入0*/
for (int i = 0; i < str->size(); i++)
{
if (str->at(i) == '-' && (i == 0 || str->at(i - 1) == '('))
{
str->insert(i, "0");
}
}
}
void lexer(string *str)
{
remove_spaces(str);
int i = 0;
bool lastWasOperatorOrOpenParenthesis = true; // 用于跟踪上一个字符是否为操作符或 '('
while (i < str->size())
{
char current = str->at(i);
if (isdigit(current))
{ // 处理连续的数字
std::string temp;
while (i < str->size() && (isdigit(str->at(i)) || str->at(i) == '.'))
{
temp.push_back(str->at(i));
i++;
}
temp_suffix_result.push(temp);
lastWasOperatorOrOpenParenthesis = false;
}
else if (isalpha(current))
{ // 处理变量名
std::string temp;
while (i < str->size() && isalpha(str->at(i)))
{
temp.push_back(str->at(i));
i++;
}
temp_suffix_result.push(temp);
lastWasOperatorOrOpenParenthesis = false;
}
else if (current == '(')
{
operators.push("(");
lastWasOperatorOrOpenParenthesis = true;
i++;
}
else if (current == ')')
{
while (!operators.empty() && operators.top() != "(")
{
temp_suffix_result.push(operators.top());
operators.pop();
}
if (!operators.empty()) operators.pop(); // 移除开括号
lastWasOperatorOrOpenParenthesis = false;
i++;
}
else if (precedence.find(current) != precedence.end())
{ // 处理操作符
if (lastWasOperatorOrOpenParenthesis)
{
if (current == '-')
{
temp_suffix_result.push("0"); // 在负号前加一个零
}
else
{
throw std::invalid_argument("无效的操作符位置");
}
}
process_operator(current, operators, temp_suffix_result);
lastWasOperatorOrOpenParenthesis = false;
i++;
}
else
{
throw std::invalid_argument("无效的字符: " + std::string(1, current));
}
}
while (!operators.empty())
{
temp_suffix_result.push(operators.top());
operators.pop();
}
}
void clear_stack(stack &s, stack &o)
{
stack empty;
s.swap(empty);
stack empty2;
o.swap(empty2);
}
// 定义函数类型
using OperatorFunc = std::function;
// 定义操作函数
double add(double left, double right) { return left + right; }
double subtract(double left, double right) { return left - right; }
double multiply(double left, double right) { return left * right; }
double divide(double left, double right) { return left / right; }
double power(double left, double right) { return std::pow(left, right); }
// 操作符映射表
std::unordered_map operatorMap = {
{"+", add},
{"-", subtract},
{"*", multiply},
{"/", divide},
{"^", power}};
double Binary_Computing_Executor(double left, double right, const std::string op)
{
auto it = operatorMap.find(op);
if (it != operatorMap.end())
{
return it->second(left, right);
}
clear_stack(temp_suffix_result, operators);
throw std::invalid_argument("未知的运算符: " + op);
}
double calculate(string *str, stack temp_suffix_result)
{
std::stack temp_resulet, temp_suffix;
while (!temp_suffix_result.empty())
{
temp_suffix.push(temp_suffix_result.top());
temp_suffix_result.pop();
}
while (!temp_suffix.empty())
{
std::string current = temp_suffix.top();
temp_suffix.pop();
if (isdigit(current[0]))
{
temp_resulet.push(current);
}
else if (isalpha(current[0]))
{ // Handle variable usage
if (variables.find(current) != variables.end())
{
temp_resulet.push(std::to_string(variables[current]));
}
else
{
clear_stack(temp_suffix_result, operators);
throw std::invalid_argument("变量 " + current + "未定义.");
}
}
else
{
if (temp_resulet.size() < 2)
{
clear_stack(temp_suffix_result, operators);
throw std::invalid_argument("无效的表达式");
}
double right = std::stod(temp_resulet.top());
temp_resulet.pop();
double left = std::stod(temp_resulet.top());
temp_resulet.pop();
double result = Binary_Computing_Executor(left, right, current);
temp_resulet.push(std::to_string(result));
}
}
if (temp_resulet.size() != 1)
{
clear_stack(temp_suffix_result, operators);
throw std::invalid_argument("无效的表达式");
}
return std::stod(temp_resulet.top());
}
void executer(string *str, SYMBOL *var)
{
Expression_optimization(str);
size_t equal_pos = str->find('=');
if (equal_pos != string::npos)
{
string var_name = str->substr(0, equal_pos);
if (isdigit(var_name[0]))
{
clear_stack(temp_suffix_result, operators);
throw std::invalid_argument("变量名不能以数字开头.");
}
string expression = str->substr(equal_pos + 1);
lexer(&expression);
double result = calculate(&expression, temp_suffix_result);
variables[var_name] = result;
std::cout << var_name << " = " << result << std::endl;
}
else
{
lexer(str);
double result = calculate(str, temp_suffix_result);
std::cout << result << std::endl;
}
std::stack empty;
temp_suffix_result.swap(empty);
std::stack empty2;
operators.swap(empty2);
}
int main()
{
bool flag = 0;
string input_str;
while (1)
{
clear_stack(temp_suffix_result, operators);
if (!flag)
cout << ">>> ";
else
flag = 0;
getline(cin, input_str);
if (input_str.empty())
{
flag = 1;
cout << ">>> ";
continue;
}
if (input_str == "exit")
break;
SYMBOL var;
try
{
executer(&input_str, &var);
}
catch (const std::invalid_argument &e)
{
std::cerr << e.what() << std::endl;
}
}
return 0;
}