#include <iostream>
#include <string>
#include <sstream>
#include <vector>
const int NumType = 0;
const int OperatorType = 1;
const int LeftBracket = 2;
const int RightBracket = 3;
const int ExprType = 4;
class Visitor;
class PrintVistor;
class Token;
class NumToken;
class OperatorToken;
class BracketToken;
class ExprToken;
// 将字符转为数字
float helpStringToNum(const std::string& text)
{
float ret;
std::stringstream ss;
ss << text;
ss >> ret;
return ret;
}
// 访问对象 抽象类
class Visitor
{
public:
virtual void apply(Token* token) = 0;
};
// 读取 虚基类
class Token
{
public:
const std::string text; // 读取的文本
const int type; // 文本类型
virtual void visit(Visitor* visitor)//
{
visitor->apply(this);
};
protected:
Token(std::string text, const int type)
:text(text), type(type) {}
virtual ~Token() {}
};
// 读取数字
class NumToken : public Token
{
public:
const float value;
NumToken(std::string text)
:Token(text, NumType)
, value(helpStringToNum(text))
{ }
};
//读取运算符
class OperatorToken : public Token
{
public:
const char op;
OperatorToken(const char op)
:Token(std::string(1, op), OperatorType)
, op(op) { }
};
// 读取括号
class BracketToken : public Token
{
public:
BracketToken(const char op)
:Token(std::string(1, op), op == '(' ? LeftBracket : RightBracket)
{ }
};
// 读入一个式子
class ExprToken : public Token
{
private:
NumToken* num;
OperatorToken* op;
ExprToken* lhs, * rhs;
bool bracket;
float calc()
{
if (op)
{
float l(lhs->value), r(rhs->value);
switch (op->op)
{
case '+': return l + r;
case '-': return l - r;
case '*': return l * r;
case '/': return l / r;
}
}
else
return num->value;
return 0;
}
public:
const float value;
ExprToken(NumToken* num)
:Token(num->text, ExprType), num(num),
op(NULL), lhs(NULL), rhs(NULL), value(calc()) {}
ExprToken(ExprToken* lhs, OperatorToken* op_, ExprToken* rhs)
:Token(lhs->text + op_->text + rhs->text, ExprType),
num(NULL), op(op_), lhs(lhs), rhs(rhs), value(calc()) {}
ExprToken(BracketToken* lb, ExprToken* expr, BracketToken* rb)
:Token(lb->text + expr->text + rb->text, ExprType),
num(NULL), op(NULL), lhs(expr), rhs(NULL),
value(expr->value)
{
bracket = true;
}
virtual void visit(Visitor* visitor)
{
if (lhs) lhs->visit(visitor);
if (rhs) rhs->visit(visitor);
visitor->apply(this);
}
virtual ~ExprToken()
{
delete num;
delete op;
delete lhs;
delete rhs;
}
};
// 输出访问对象
class PrintVistor : public Visitor
{
private:
int line;
public:
PrintVistor() : line(0) {}
virtual void apply(Token* token)
{
if (token->type == ExprType)
{
ExprToken* expr = dynamic_cast<ExprToken*>(token);
std::cout << '#' << ++line << ": "
<< token->text << " = ";
if (expr)
std::cout << expr->value;
else
std::cout << "NaN";
std::cout << std::endl;
}
}
};
// 将算式存入vector 匹配类型
std::vector<Token*> parse(std::string text)
{
std::vector<Token*> vec;
for (int i = 0; i < text.length(); ++i)
{
switch (text[i])
{
case ' ':
break;
case '+':
case '-':
case '*':
case '/':
vec.push_back(new OperatorToken(text[i]));
break;
case '(':
case ')':
vec.push_back(new BracketToken(text[i]));
break;
default:
{
int r;
for (r = i; r < text.length() && text[r] >= '0'
&& text[r] <= '9'; ++r);
vec.push_back(new NumToken(text.substr(i, r - i)));
i = r - 1;
}
}
}
return vec;
}
// 判断类型
bool is_expr(Token* lhs, Token* op, Token* rhs, bool priority = false)
{
if (lhs->type != ExprType
|| op->type != OperatorType
|| rhs->type != ExprType)
return false;
OperatorToken* _op = dynamic_cast<OperatorToken*>(op);//将基类指针转化为派生类指针
return _op && (!priority ^ ((_op->op == '*') || (_op->op == '/')));
}
// 计算
void compile(std::vector<Token*>& vec)
{
for (int i = 0; i < vec.size(); ++i)
if (vec[i]->type == NumType)
{
NumToken* num = dynamic_cast<NumToken*>(vec[i]);
if (num)//如果为数字则将其转为初始expr
vec[i] = new ExprToken(num);
else
vec[i] = new ExprToken(new NumToken("0"));
}
while (vec.size() > 1)
{
bool flag = false;
// 先计算= '(' expr ')'
for (int i = 0; i < vec.size() - 2; ++i)
{
if (vec[i]->type == LeftBracket && vec[i + 2]->type == RightBracket
&& vec[i + 1]->type == ExprType)
{
flag = true;
ExprToken* expr = new ExprToken(
dynamic_cast<BracketToken*>(vec[i]),
dynamic_cast<ExprToken*>(vec[i + 1]),
dynamic_cast<BracketToken*>(vec[i + 2]));
vec.erase(vec.begin() + i + 1, vec.begin() + i + 3);
vec[i] = expr;
}
if (flag) break;
}
if (flag) continue;
// 再计算expr '*' expr
// 再计算 expr '/' expr
for (int i = 0; i < vec.size() - 2; ++i)
{
if (is_expr(vec[i], vec[i + 1], vec[i + 2], true))
{
flag = true;
ExprToken* expr = new ExprToken(
dynamic_cast<ExprToken*>(vec[i]),
dynamic_cast<OperatorToken*>(vec[i + 1]),
dynamic_cast<ExprToken*>(vec[i + 2]));
vec.erase(vec.begin() + i + 1, vec.begin() + i + 3);
vec[i] = expr;
}
if (flag) break;
}
if (flag) continue;
// 计算expr '+' expr
// 计算 expr '-' expr
for (int i = 0; i < vec.size() - 2; ++i)
{
if (is_expr(vec[i], vec[i + 1], vec[i + 2]))
{
if (i > 0 && vec[i - 1]->type == OperatorType
&& (dynamic_cast<OperatorToken*>(vec[i - 1])->op == '*'
|| dynamic_cast<OperatorToken*>(vec[i - 1])->op == '/'))
continue;
if (i + 3 < vec.size() && vec[i + 3]->type == OperatorType
&& (dynamic_cast<OperatorToken*>(vec[i + 3])->op == '*'
|| dynamic_cast<OperatorToken*>(vec[i + 3])->op == '/'))
continue;
flag = true;
ExprToken* expr = new ExprToken(
dynamic_cast<ExprToken*>(vec[i]),
dynamic_cast<OperatorToken*>(vec[i + 1]),
dynamic_cast<ExprToken*>(vec[i + 2]));
vec.erase(vec.begin() + i + 1, vec.begin() + i + 3);
vec[i] = expr;
}
if (flag) break;
}
if (!flag)
{
std::cout << "error" << std::endl;
return;
}
}
PrintVistor v;
vec[0]->visit(&v);
}
int main(int argc, char* argv[])
{
std::string s;
std::cin >> s;
std::vector<Token*> vec = parse(s);
compile(vec);
return 0;
}
计算器小程序
最新推荐文章于 2024-09-05 17:46:44 发布
本文介绍了使用C++实现的一个数学表达式解析器,包括Token、ExprToken等类的设计,以及parse和compile函数,用于处理和计算输入的算式。
摘要由CSDN通过智能技术生成