#include <iostream>
#include <stack>
#include <vector>
#include <string>
#define uint unsigned int
using namespace std; //判断该字符是否为运算符 是则返回真 否则返回假
inline bool isOperator(char opr)
{
switch(opr)
{
case '*':
return true;
case '/':
return true;
case '+':
return true;
case '-':
return true;
default:
return false;
}
}
//Sufexp(string& ,vector<string>& ); //翻译为后缀表达式 suffic expression
//第一个参数为输入表达式字符串引用,第二个参数为放置后缀表达式的向量引用
//从首至尾分别为数字和运算符 没有检查功能
void Sufexp(string &str,vector<string> &str_vec)
{
stack<string,vector<string> > sta; string::size_type longth = str.size();
int last_flag = -1;
for(int i = 0;i < longth;i++)
{
//如果第i个字符串是运算符 则进入大判断
if(str.at(i) == '*' || str.at(i) == '/' || str.at(i) == '+' || str.at(i) == '-' || str.at(i) == '(' || str.at(i) == ')'|| str.at(i) == '=')
{
//如果是左括号则需要改变last_flag
if(str.at(i) == '(' )
{
last_flag = i;
}
//如果右括号右边紧跟运算符则需要改变last_flag
else if(str.at(i-1) == ')' && isOperator(str.at(i)))
{
last_flag = i;
}
//遇到右括号紧跟等号也不需要分割 遇到右括号紧跟运算符不需要分割
else if(!((str.at(i-1) == ')' && str.at(i) == '=') || (str.at(i-1) == ')' && isOperator(str.at(i)))))
{
str_vec.push_back(str.substr(last_flag + 1,i - last_flag -1));
last_flag = i;
} //如果栈为空 直接将符号入栈
if(sta.size()==0)
{
char ch[1] = {str.at(i)};
string str_1(ch,1);
sta.push(str_1);
} //如果栈不为空
//如果检测到 '(' 直接入栈
else if(str.at(i) == '(')
{
char ch[] = {str.at(i)};
string str_1(ch,1);
sta.push(str_1);
}
//如果检测到的是高级运算符先将之前的高级弹出的字符串项链在将新运算符入栈
else if(str.at(i) == '*' || str.at(i) == '/')
{
if(sta.top() == "*" || sta.top() == "/")
{
str_vec.push_back(sta.top());
sta.pop();
}
char ch[] = {str.at(i)};
string str_1(ch,1);
sta.push(str_1);
}
//如果检测到的是低级运算符需要将高级运算符弹出 同级运算符也需要先弹出再入栈 低级运算符再入栈
else if(str.at(i) == '+' || str.at(i) == '-')
{
bool once = false ;
//判断之前的运算符是否为高级运算符 如果是
while((sta.top() == "*" || sta.top() == "/") && sta.size() != 0 )
{ //先将 高级 运算符弹出放入字符串向量 str_vec.push_back(sta.top());
sta.pop(); once = true;
if(sta.size() == 0) break; } //如果曾经把高级运算符弹出去过 就不用将现在栈顶运算符弹出了 否则就弹出一次
if(once == false && sta.size() != 0)
{
if(sta.top() == "+" || sta.top() == "-")
{
str_vec.push_back(sta.top());
sta.pop();
//if(sta.size() == 0) break;
}
}
//再将低级运算符压栈
char ch[] = {str.at(i)};
string str_1(ch,1);
sta.push(str_1);
}
//如果检测到 ')' 将栈中的符号逐个弹出 直至遇到 '('
else if(str.at(i) == ')')
{
while(sta.top() != "(")
{
str_vec.push_back(sta.top());
sta.pop();
if(sta.size() == 0) break;
}
//将'('直接弹出而不放入字符串向量
if(sta.top() == "(")
{
//cout << sta.top() << endl;
sta.pop();
} }
//如果检测到是 '=' 将栈中数据全部弹出至字符串向量 最后将'='存入字符串向量
//输出后缀表达式
else if(str.at(i) == '=')
{ //将栈中数据全部弹出至字符串向量
while(sta.size() != 0)
{
str_vec.push_back(sta.top());
sta.pop();
} //最后将'='存入字符串向量
str_vec.push_back("="); vector<string>::iterator begin = str_vec.begin();
vector<string>::iterator end = str_vec.end(); //如果向量中有空字符串 可以去除有括号与运算符紧挨在一起由substr引起的空字符串
/*for( ;begin != str_vec.end(); begin++)
{
if((*begin) == "")
{
str_vec.erase(begin);
begin--;
}
}*/ //输出后缀表达式
/*cout << "后缀表达式:" << endl;
begin = str_vec.begin();
end = str_vec.end();
for( ;begin != end;begin++)
{
//显示第n个元素的下标与对应元素内容
cout << distance(str_vec.begin(),begin) << "\t" << *begin << endl;
}
cout << endl;*/
}
}
}
} //向量内的元素遍历显示
void showVecFac(vector<string> str_vec)
{
vector<string>::iterator begin = str_vec.begin();
vector<string>::iterator end = str_vec.end();
for(;begin != end;begin++)
{
cout << *begin << "\t" ;
}
cout << endl;
} //计算后缀表达式
void calSuf(vector<string> &str_vec)
{
//向量遍历
for(vector<string>::iterator begin = str_vec.begin();begin != str_vec.end();begin++)
{
vector<string>::iterator temp_begin = begin; //中间迭代器变量
const char *first_char;
const char *second_char;
string result;
char temp_str_result[50];
double temp_double; const char *answer;
bool point = false;
uint last_num = 0;
uint i = 0; //将字符串转换为char形
const char *temp_char = (*begin).c_str(); //处理基本运算
switch(*temp_char)
{
case '*':
//提取运算符前边两个数据 用于计算
--temp_begin;
second_char = (*temp_begin).c_str();
--temp_begin;
first_char = (*temp_begin).c_str(); //运算
temp_double = atof(first_char) * atof(second_char); /*cout << "first_char : " << first_char << endl;
cout << "second_char : " << second_char << endl;
cout << temp_double << endl;*/ //将数据替换到begin
sprintf(temp_str_result, "%lf", temp_double);
result = temp_str_result;
(*begin) = result; //清除空余数据
str_vec.erase(temp_begin);
begin--;
str_vec.erase(temp_begin);
begin--;
break;
case '/':
//提取运算符前边两个数据 用于计算
--temp_begin;
second_char = (*temp_begin).c_str();
--temp_begin;
first_char = (*temp_begin).c_str(); //运算
temp_double = atof(first_char) / atof(second_char); //将数据替换到begin
sprintf(temp_str_result, "%lf", temp_double);
result = temp_str_result;
(*begin) = result; //清除空余数据
str_vec.erase(temp_begin);
begin--;
str_vec.erase(temp_begin);
begin--;
break; case '+':
//提取运算符前边两个数据 用于计算
--temp_begin;
second_char = (*temp_begin).c_str();
--temp_begin;
first_char = (*temp_begin).c_str(); //运算
temp_double = atof(first_char) + atof(second_char); //将数据替换到begin
sprintf(temp_str_result, "%lf", temp_double);
result = temp_str_result;
(*begin) = result; //清除空余数据
str_vec.erase(temp_begin);
begin--;
str_vec.erase(temp_begin);
begin--;
break;
case '-':
//提取运算符前边两个数据 用于计算
--temp_begin;
second_char = (*temp_begin).c_str();
--temp_begin;
first_char = (*temp_begin).c_str(); //运算
temp_double = atof(first_char) - atof(second_char); //将数据替换到begin
sprintf(temp_str_result, "%lf", temp_double);
result = temp_str_result;
(*begin) = result; //清除空余数据
str_vec.erase(temp_begin);
begin--;
str_vec.erase(temp_begin);
begin--;
break; case '=':
//判断结构是否为小数
//判断是否为整数
answer = (*(begin-1)).c_str();
point = false;
last_num = 0;
i = 0;
while(answer[i])
{ if(answer[i] == '.')
{
point = true;
}
if(point == true && answer[i] != '0')
{
last_num = i;
} i++;
}
//判断最后一位是不是小数点 区别对待
if(answer[last_num] == '.')
{
--last_num;
}
*(begin-1) = (*(begin-1)).substr(0,last_num + 1);
break;
default:
break;
}
}
//清除末尾的等号 只存储最终结果
str_vec.erase(str_vec.end()-1);
} //用于输出结果
void showAnswer(vector<string> & str_vec)
{
cout << "the result is : " << *(str_vec.begin()) << endl;
} int main()
{
string str;
cin >> str;
//末尾自动添加 等号
str += "=";
//用于存放后缀表达式
vector<string> str_vec;
//通过函数 得到后缀表达式的向量 存放在str_vec向量中
//第一个参数为输入表达式字符串引用,第二个参数为放置后缀表达式的向量引用,从首至尾分别为数字和运算符
//没有检查功能
Sufexp(str,str_vec); //计算后缀表达式 并存放在str_vec向量中
calSuf(str_vec); showAnswer(str_vec); //直接输入运算符可以借用上一次结果继续运算
while(1)
{
cin >> str;
str += "=";
//如果紧跟上次的结果的是运算符 就接着运算 否则展开新运算与上次结果无关
if(str.at(0) == '*' || str.at(0) == '/' || str.at(0) == '+' || str.at(0) == '-')
{
str = (*(str_vec.end()-1)) + str;
} str_vec.clear();
Sufexp(str,str_vec);
//计算后缀表达式 并存放在str_vec向量中
calSuf(str_vec); showAnswer(str_vec);
} return 0;
}

关于使用栈将一般运算式翻译为后缀表达式并实现三级运算的方法及实例(cpp版)的更多相关文章

  1. 深入浅出数据结构C语言版(8)——后缀表达式、栈与四则运算计算器

    在深入浅出数据结构(7)的末尾,我们提到了栈可以用于实现计算器,并且我们给出了存储表达式的数据结构(结构体及该结构体组成的数组),如下: //SIZE用于多个场合,如栈的大小.表达式数组的大小 #de ...

  2. Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算

    中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...

  3. 中缀表达式转后缀表达式(用于求字符串表达式值)(js栈和队列的实现是通过数组的push和unshift方法插值,pop方法取值)

    中缀表达式:就是我通常用的算术或逻辑公式: 后缀表达式:不包含括号,运算符放在两个运算对象后面,所有的计算按运算符出现的顺序,严格从左向右进行,不用考虑运算符优先级: 如,(2+1)*3 转换后,2 ...

  4. javascript使用栈结构将中缀表达式转换为后缀表达式并计算值

    1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ...

  5. 《java数据结构与算法》笔记-CH4-8栈结构实现后缀表达式计算结果

    /** * 中缀表达式转换成后缀表达式: 从输入(中缀表达式)中读取的字符,规则: 操作数: 写至输出 左括号: 推其入栈 右括号: 栈非空时重复以下步骤--> * 若项不为(,则写至输出: 若 ...

  6. 栈的应用1——超级计算器(中缀与后缀表达式)C语言

    这里要学的程序主要用来实现一个功能——输入表达式输出结果,也就是一个计算器.效果如下: 这个程序主要有两个步骤:1.把中缀表达式转换为后缀表达式:2.计算后缀表达式的结果. 首先先明白几个问题: 1. ...

  7. 栈应用之 后缀表达式计算 (python 版)

    栈应用之 后缀表达式计算 (python 版) 后缀表达式特别适合计算机处理 1.  中缀表达式.前缀表达式.后缀表达式区别  中缀表达式:(3 - 5) * (6 + 17 * 4) / 3 17 ...

  8. c++实验4 栈及栈的应用+回文+中、后缀表达式

    栈及栈的应用+回文+中.后缀表达式 1.栈顺序存储结构的基本操作算法实现 (1)栈顺序存储结构的类定义: class SeqStack { private: int maxsize; DataType ...

  9. 数据结构(3) 第三天 栈的应用:就近匹配/中缀表达式转后缀表达式 、树/二叉树的概念、二叉树的递归与非递归遍历(DLR LDR LRD)、递归求叶子节点数目/二叉树高度/二叉树拷贝和释放

    01 上节课回顾 受限的线性表 栈和队列的链式存储其实就是链表 但是不能任意操作 所以叫受限的线性表 02 栈的应用_就近匹配 案例1就近匹配: #include <stdio.h> in ...

随机推荐

  1. RobotFramework下的http接口自动化post关键字的使用

    在http协议中,除了get请求外,另一个最常用的就是post请求了.和get 请求类似,post请求接收一个参数,[ url ] 示例1:调用博客园(http://www.cnblogs.com/) ...

  2. 关系型数据库工作原理-客户端连接管理器(翻译自Coding-Geek文章)

    本文翻译自Coding-Geek文章:< How does a relational database work>.原文链接:http://coding-geek.com/how-data ...

  3. Hadoop3.0完全分布式集群安装部署

    1. 配置为1个namenode(master主机),2个datanode(slave1主机+slave2主机)的hadoop集群模式, 在VMWare中构建3台运行Ubuntu的机器作为服务器: 关 ...

  4. Java最大公约数和最小公倍数的求法(辗转相除法)

    这道题计算了三个数的最小公倍数 import java.util.Scanner; public class D { public static int gcd(int a,int b) { int ...

  5. 进程优化工具Process Lasso Pro 8.4官方版+激活破解方法

    Process Lasso是一款来自美国的系统进程优化工具,基于特殊算法动态调整进程的优先级别,通过合理的设置进程优先级来实现降低系统负担的功能.可有效避免蓝 屏.假死.进程停止响应.进程占用 CPU ...

  6. linux下关闭网络命令

    CTRL+ALT+F1 进入命令行模式 CTRL+ALT+F7 退出命令行模式 sudo ifconfig ethX dwon 关闭网卡sudo /etc/init.d/networking stop ...

  7. 关于js高度和宽度的获取 ----2017-03-29

    来源:百度  对错有待实践检验 网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: docu ...

  8. Java中调用文件中所有bat脚本

    //调用外部脚本String fileips=null;//所有的路径String[] files=null;String fileip=null;//单个路径try { InputStream is ...

  9. Python进阶_类与实例

    上一节将到面对对象必须先抽象模型,之后直接利用模型.这一节我们来具体理解一下这句话的意思. 面对对象最重要的概念就是类(class)和实例(instance),必须牢记类是抽象的模板,比如studen ...

  10. SpringMVC的工作流程以及组件说明

    1. SpringMVC处理流程 2. SpringMVC架构 2.1 框架结构 2.2 框架流程 1. 用户发送请求至前端控制器DispatcherServlet. 2. DispatcherSer ...