写一个简单的计算器并不是什么很难的事,主要目的是要通过这个程序来学习和分析其中的核心算法。这个简易计算器的核心部分就是对输入的表达式的正确性判断与求值,其中包括对表达式的解析、中缀表达式转后缀表达式、后缀表达式求值等等几个方面。
一、封装核心代码
《算术表达式的合法性判断与求值(上)》和《算术表达式的合法性判断与求值(下)》这两篇文章已经对核心算法部分进行了讲解,并附有源码。在此基础上制作一个简单计算器,我们要做的仅仅是封装核心代码并加入MFC工程中。
下面是我封装的一个 Expression 类:
Expression.h
#pragma once
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stack>
#include <utility>
using namespace std;
class Expression
{
public:
Expression(string str);
bool test(); // 外部接口,判断表达式是否合法
double calculate(); // 外部接口,计算表达式的值
private:
vector<pair<string, int>> word;
string expr; // 算术表达式
int idx; // word下标
int sym; // 单词种别编码
int err; // 错误
int word_analysis(vector<pair<string, int>>& , const string);
void Next();
void E();
void T();
void F();
bool Right; // 保存表达式test结果
private:
int prior(int); // 获取运算符的优先级
bool isOperator(int); // 通过 种别编码 判定是否是运算符
vector<pair<string,int>> getPostfix(const vector<pair<string,int>>&); // 中缀转后缀
void popTwoNumbers(stack<double>&, double&, double&); // 从栈中连续弹出两个操作数
double stringToDouble(const string&); // 把string转换为double
double expCalculate(const vector<pair<string, int>>&); // 计算后缀表达式的值
};
Expression.cpp
#include "Expression.h"
// 构造函数
Expression::Expression( string str ):
expr(str),
idx(0),
err(0),
Right(true)
{
}
// 外部接口
bool Expression::test()
{
if(!word.empty()) // 已经test过了
{
return Right;
}
int err_num = word_analysis(word, expr);
if (-1 == err_num)
{
Right = false;
}
else
{
// 词法正确,进行语法分析
Next();
E