刚开始学,请大佬们看一看有没有啥问题。
"MyStack.h"
#pragma once
#include <iostream>
using namespace std;
template<class T>//结点
class LinkNode
{
public:
T data;//数据域
LinkNode* next;//指针域
};
template<class T>
class LinkStack//栈
{
public:
//初始化链栈
LinkStack();
//元素入栈
void Push(T c);
//元素出栈
void Pop();
//判断栈是否为空
bool isEmpty();
//获取栈顶元素,并用x接收
T GetTop();
//获取栈长度
int Length();
private:
LinkNode<T>* HeadNode;//头结点
int len;
};
template<class T>
LinkStack<T>::LinkStack()
{
HeadNode = new LinkNode<T>();
HeadNode->next = NULL;
len = 0;
}
//元素入栈
template<class T>
void LinkStack<T>::Push(T c)
{
LinkNode<T>* p = new LinkNode<T>();
p->data = c;
p->next = HeadNode->next;
HeadNode->next = p;
++len;
}
//元素出栈
template<class T>
void LinkStack<T>::Pop()
{
LinkNode<T>* p = HeadNode->next;
if (p == NULL)
return;
HeadNode->next = p->next;
delete p;
--len;
}
//判断栈是否为空
template<class T>
bool LinkStack<T>::isEmpty()
{
LinkNode<T>* p = HeadNode->next;
if (p == NULL)
return true;
else
return false;
}
//获取栈顶元素,并返回
template<class T>
T LinkStack<T>::GetTop()
{
if (!isEmpty())
return HeadNode->next->data;
else
return NULL;
}
//获取栈的长度
template <class T>
int LinkStack<T>::Length()
{
return len;
}
BracketMatch.h
#pragma once
#include <iostream>
using namespace std;
//判断输入的计算式括号是否合法
bool Bracket_isMatched(string str);
//输入计算式,储存在字符串str中
string EnString();
BracketMatch.cpp
#include"MyStack.h"
#include"BracketMatch.h"
#include <iostream>
#include<string>
using namespace std;
//判断括号是否合法
/*
1.初始化一个链栈,遍历传进来的字符串,
遇到左括号则入栈,遇到右括号则:
判断栈是否为空,若为空则表明不匹配;
若栈不为空,将栈顶元素出栈,并检验是否与当前右括号匹配;
2.遍历完成后,检验栈是否为空,若为空则括号匹配成功;否则,括号匹配失败
*/
//输入计算式,储存在字符串str中
string EnString()
{
string str;
getline(cin, str);
return str;
}
//判断输入的计算式括号是否合法
bool Bracket_isMatched(string str)
{
LinkStack<char> S;
for (int i = 0; i != str.length(); ++i)
{
if (str[i] == '(' || str[i] == '[' || str[i] == '{')
S.Push(str[i]);
else if (str[i] == ')' || str[i] == ']' || str[i] == '}')
{
if (S.isEmpty())
return false;
else
{
char temp = S.GetTop();
S.Pop();
if (temp == '(' && str[i] != ')' || temp == '[' && str[i] != ']'
|| temp == '{' && str[i] != '}')
return false;
}
}
}
return S.isEmpty();
}
Calculate.h
#pragma once
#include <iostream>
#include"MyStack.h"
using namespace std;
//用栈计算中缀表达式
int Calculate();
//运算
int opera(int left, int right, char c);
//判断运算符优先级,判断c1优先级是不是小于或等于c2
bool Priority(char c1, char c2);
//弹出并获取一个运算符,弹出并获取操作数,计算之后将结果压入操作数栈
void GetCalculate(LinkStack<char>& S_char, LinkStack<int>& S_int);
Calculate.cpp
#include<iostream>
#include"Calculate.h"
#include"BracketMatch.h"
#include"MyStack.h"
using namespace std;
/*
1.用栈实现中缀表达式转后缀表达式
初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾。可能遇到三种情况:
①遇到操作数。直接加入后缀表达式;
②遇到界限符。遇到"("直接入栈;遇到")"则一次弹出栈内运算符并加入
后缀表达式,直到弹出"("为止。注意"("不加入后缀表达式
③遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,
并加入后缀表达式
*/
/*
2.用栈实现后缀表达式计算
1.从左往右扫描下一个元素,直到处理完所有元素
2.若扫描到操作数则压入栈,并回到1.;否则执行3.
3.若扫描到运算符。则弹出栈顶的连个元素,执行相应的运算,运算结果压回
栈顶,回到1.
*/
/*
3.用栈实现中缀表达式的计算
初始化两个栈,操作数栈和运算符栈
若扫描到操作数,则压入操作数栈
若扫描到运算符或界限符,则按照“中缀转后缀相同的逻辑压入运算符栈(
期间也会弹出运算符,每当弹出一个运算符时,就需要弹出两个操作数栈的
栈顶元素并执行相应运算,运算结果再压回操作数栈)”
*/
//运算
int opera(int left,int right,char c)
{
if (c == '+')
return left + right;
else if(c=='-')
return left - right;
else if(c=='*')
return left * right;
else if(c=='/')
return left / right;
}
//弹出并获取一个运算符,弹出并获取操作数,计算之后将结果压入操作数栈
void GetCalculate(LinkStack<char>& S_char, LinkStack<int>& S_int)
{
char c = S_char.GetTop();
S_char.Pop();
int left, right;
//获取操作数
right = S_int.GetTop();
S_int.Pop();
left = S_int.GetTop();
S_int.Pop();
//进行计算,并压入操作数栈
S_int.Push(opera(left, right, c));
}
//判断运算符优先级,判断c1优先级是不是小于或等于c2
bool Priority(char c1, char c2)
{
if ((c1 == '*' || c1 == '/') && (c2 == '+' || c2 == '-'))
return false;
else
return true;
}
//用栈计算中缀表达式
int Calculate()
{
string str = EnString();
if (Bracket_isMatched(str))
{
LinkStack<char> S_char;//运算符栈
LinkStack<int> S_int;//操作数栈
int num = 0;
int flag = 0;
for (int i = 0; i != str.length(); ++i)
{
if(str[i] >= '0' && str[i] <= '9')//若遇到数字则将字符转换为数字
{
num = num * 10 + str[i] - '0';
++flag;
if (flag != 0 && i == str.length() - 1)
{
S_int.Push(num);//数字转换结束后压入操作数栈
num = 0;//num清零
flag = 0;
}
}
else
{
if (flag != 0)//说明num被修改过
{
S_int.Push(num);//数字转换结束后压入操作数栈
num = 0;//num清零
flag = 0;
}
if (str[i] == '(')//遇到'('直接入运算符栈
S_char.Push(str[i]);
else if (str[i] == ')')
{
while (S_char.GetTop() != '(' )
{
GetCalculate(S_char, S_int);
}
S_char.Pop();
}
else if (str[i] == '+' || str[i] == '-' || str[i] == '*' ||
str[i] == '/')
{
while (S_char.GetTop() != '('&& !S_char.isEmpty()
&& Priority(str[i], S_char.GetTop()))
{
GetCalculate(S_char, S_int);
}
S_char.Push(str[i]);
}
}
}
while (!S_char.isEmpty())//判断操作符栈是否空,不空则进行计算
{
GetCalculate(S_char, S_int);
}
return S_int.GetTop();
}
else
{
cout << "括号不匹配" << endl;
return -9999;
}
}
main.cpp
#include <iostream>
#include"MyStack.h"
#include"BracketMatch.h"
#include"Calculate.h"
using namespace std;
int main()
{
cout << Calculate() << endl;
return 0;
}