1.目的:
实现中缀表达式转为后缀,并计算得到计算结果输出显示。
2.输入输出介绍:
在英文输入下,键入你的表达式(注:这里只实现了 +-*/ 没有更复杂的幂次等计算)
之后,你将看到输出三部分:
①.将您输入的表达式的数字部分 和 操作符部分 分开,以独占一行的方式打印输出;
②.表达式的后缀输出;
③.计算结果。
3.完整代码,照例,无偿放在这里了:
/*
1.要实现的目标是:根据输入的数学表达式,得到计算结果
2.分析:
数学表达式使用 字符串接受;
从表达式中摘出来需要得到数字部分;
需要两个栈
字符串类型的;一个栈用于中缀表达式转后缀;一个在后缀计算结果时候用
*/
// 栈 先使用自定义实现;后面可以改成使用 STL容器
#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<ctype.h> // 当判断的字符是数字时,函数返回1~9的非零值,当判断的字符不是数字时,函数返回 0
// 自定义栈的数据结构
typedef struct lNode{
string data;
struct lNode* next;
}LNode, *LinkStack;
// 初始化 构造成不带头结点的
void init(LinkStack& s)
{
s = NULL;
}
// 判空
bool isEmpty(LinkStack s)
{
if (s == NULL)
return true;
else
{
return false;
}
}
// 进栈操作 为了方便对栈顶的操作 这里使用 --- 新元素 指向 老元素 --- 的结构
void pushStack(LinkStack& s, string ele)
{
LNode* newNode = new LNode;
newNode->data = ele;
newNode->next = s;
s = newNode; // 由于 要改变 栈顶指针的值 这里需要使用引用
}
// 出栈操作
void popStack(LinkStack& s, string& ret)
{
if (isEmpty(s))
{
return;
}
ret = s->data;
LNode* temp = s;
s = s->next;
delete temp;
}
// 读栈顶元素
string getTop(LinkStack s)
{
if (!isEmpty(s))
{
return s->data;
}
}
//销毁栈
void destroyStack(LinkStack& s)
{
LNode* temp = s;
while (temp != NULL)
{
LNode* nextNode = temp->next;
delete temp;
temp = nextNode;
}
s = NULL; // 将外部栈指针置为 NULL
}
// 获取用户输入
string getExpression()
{
string expression;
cout << "请输入您的表达式,以回车结束" << endl;
getline(cin, expression);
return expression;
}
// 中缀转后缀
// 首先将 数字 与 +-*/ 操作符 区分出来,放入容器中,, 比如把 (32.1+2)*7/4 分成 ( 32.1 + 2 ) * 7 / 4
vector<string> lookBetter(string expression)
{
vector<string> vS;
string str;
for (auto c : expression)
{
if (isdigit(c) || c =='.')
{
str += c;
}
else
{
if (!str.empty())
{
vS.push_back(str);
str.clear();
}
if (c == ' ')
{
// 跳过空格
continue;
}
str = c;
vS.push_back(str);
str.clear();
}
}
if (!str.empty())
{
vS.push_back(str);
str.clear();
}
return vS;
}
// 判断字符串 是否可以转成小数
bool isNumber(const string& str) // 使用 const 限定不能修改; 使用引用直接在本体上操作,不需要复制一份,提高性能
{
try {
stod(str); // 字符串 转 double类型
return true;
}
catch(const invalid_argument& e)
{
return false;
}
catch (const out_of_range& e)
{
return false;
}
}
// 中缀表达式 转后缀
vector<string> mid2back(string expression)
{
LinkStack S;
init(S);
vector<string> ret;
vector<string> vS = lookBetter(expression);
for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
{
if (isNumber(*itBegin)) // 如果是数字部分 直接放入后缀容器
{
ret.push_back(*itBegin);
}
else
{
// 这里用的 string 类型,需要使用双引号
if ((*itBegin) == "(") // 如果是"(" 直接入栈
{
pushStack(S, (*itBegin));
}
if ((*itBegin) == "+" || (*itBegin) == "-") // 如果是 "+"或"-" 将栈中遇到的所有+—*/ 出栈,,直到遇到第一个非 +—*/ ,,之后再将自己入栈
{
if (isEmpty(S))
pushStack(S, (*itBegin));
else
{
while (!isEmpty(S) && (getTop(S) == "+" || getTop(S) == "-" || getTop(S) == "*" || getTop(S) == "/"))
{
// 这里的非空判断是必要的 场景为 2+3-1 时 -将+出栈后,栈由非空变为空
string popEle;
popStack(S, popEle);
ret.push_back(popEle);
}
pushStack(S, (*itBegin));
}
}
if ((*itBegin) == "*" || (*itBegin) == "/") // 如果是 "*"或"/" 将栈中遇到的所有 */ 出栈,,直到遇到第一个非 */ ,,之后再将自己入栈
{
if (isEmpty(S))
pushStack(S, (*itBegin));
else
{
while (!isEmpty(S) && getTop(S) == "*" || getTop(S) == "/")
{
string popEle;
popStack(S, popEle);
ret.push_back(popEle);
}
pushStack(S, (*itBegin));
}
}
if ((*itBegin) == ")") // 如果是")" 将遇到的"("之前的所有元素出栈放入后缀容器中,
{
string popEle;
while (getTop(S) != "(")
{
popStack(S, popEle);
ret.push_back(popEle);
}
popStack(S, popEle); // 将"(" 出栈,不添加到 后缀容器中 ")"不入栈
}
}
}
// 最后 如果 栈内非空,将栈中元素 出栈
while (!isEmpty(S))
{
string popEle;
popStack(S, popEle);
ret.push_back(popEle);
}
return ret;
}
// 计算后缀表达式 得到正确结果
double compute(vector<string> vS)
{
LinkStack S2;
init(S2);
for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
{
if (isNumber(*itBegin)) // 如果是数字 直接入栈
{
pushStack(S2, *itBegin);
}
else
{
string leftValue;
string rightValue;
popStack(S2, rightValue); // 先出栈的为右值
popStack(S2, leftValue);
if (*itBegin == "+")
{
double l = stod(leftValue);
double r = stod(rightValue);
pushStack(S2, to_string(l + r));
}
if (*itBegin == "-")
{
double l = stod(leftValue);
double r = stod(rightValue);
pushStack(S2, to_string(l - r));
}
if (*itBegin == "*")
{
double l = stod(leftValue);
double r = stod(rightValue);
pushStack(S2, to_string(l * r));
}
if (*itBegin == "/")
{
double l = stod(leftValue);
double r = stod(rightValue);
pushStack(S2, to_string(l / r));
}
}
}
if (!isEmpty(S2))
{
string ret;
popStack(S2, ret);
double retValue = stod(ret);
return retValue;
}
}
// 测试案例
void test()
{
string expression = getExpression();
vector<string> vS = lookBetter(expression);
for (auto ele : vS)
{
cout << ele << endl;
}
cout << "----------------------" << endl;
vector<string> mB = mid2back(expression);
for (string ele : mB)
{
cout << ele<<" ";
}
cout << endl << "----------------------" << endl;
double value = compute(mB);
cout << "计算结果是:" << value << endl;
}
int main()
{
test();
system("pause");
return 0;
}