#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. 基于puppet分布式集群管理公有云多租户的架构浅谈

    基于puppet分布式集群管理公有云多租户的架构浅谈 一.架构介绍   在此架构中,每个租户的业务集群部署一台puppet-master作为自己所在业务集群的puppet的主服务器,在每个业务集群所拥 ...

  2. shell 脚本下执行Mongodb命令

    最近项目中搭建了两台mongodb的服务器,由于服务器只有两台的情况下,目前只是搭建了主从模式架构(官方目前并不推荐主从模式),缺点就是故障转移不变等等原因,而是推荐副本集模式(这里就不多说了)... ...

  3. Solidity by Example详解 - Voting

    Example地址:https://solidity.readthedocs.io/en/develop/solidity-by-example.html#voting Voting程序的功能: 这个 ...

  4. github远程仓库初始化配置

    github远程仓库的提交一般是通过shell进行,windows下有Git Bash工具(https://git-for-windows.github.io/) 由于本地Git仓库和GitHub仓库 ...

  5. Object类----toString,equals,hashcode

    一.toString 的应用方法与覆写 public class testoveridetoString { public static void main(String[] args) { /*ob ...

  6. JDK1.8源码(二)——java.lang.Integer 类

    上一篇博客我们介绍了 java.lang 包下的 Object 类,那么本篇博客接着介绍该包下的另一个类 Integer.在前面 浅谈 Integer 类 博客中我们主要介绍了 Integer 类 和 ...

  7. Python的Argparse模块是什么?(未完)

            近日在阅读代码的过程中遇到了Argparse模块,记得前段时间已经看了,可是过了两周现在又忘了, 看来写代码一定要钻研到底搞清楚其中原委才行,本文主要参考Python3.6系列官方文档 ...

  8. Ubuntu16.04 中 Vscode 如何断点调试C语言程序

    个人博客链接:Ubuntu16.04 中 Vscode 如何断点调试C语言程序 问题:环境是 Ubuntu16.04,如何使用 Vscode 断点调试C语言程序. 写代码没有调试环境是不能忍受的,所以 ...

  9. [模拟赛] T3 Exploit

    Description 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以"EX"为开头的英语单词. eXplore(探索) eXpand(拓张与发展 ...

  10. 【Zabbix】在CentOS7上安装Zabbix3.0

    Zabbix安装 首先说明一下,本文主要参考了[http://www.linuxidc.com/Linux/2016-11/137030.htm]和[http://www.cnblogs.com/XY ...