c++ 中缀表达式转后缀表达式 计算器

来源:互联网 发布:ci 数据库配置 编辑:程序博客网 时间:2024/06/05 00:47

calc_res里面使用空格分割是个很不好的情况..需要保证转换的后缀式+-/*操作符是连在一起的 每个数字都需要用空格分离 ... 

我懒的改了..这样导致代码逻辑有些乱 因为计算的后缀式res需要整理好才能计算正确  


//数据结构与算法分析 栈c++实现  //缺点 需要一次性分配足够的栈空间 没有实现动态变长 //优点 大部分操作的消耗都是常量级别的template <class type>class stack{public:stack(){}~stack() { destroy(); }voidcreate_stack(size_t max_element){if (!m_stack_base_ptr){m_stack_base_ptr = new type[max_element];m_max_element = max_element;}}voidpush(type &t){if(!is_full())m_stack_base_ptr[++m_top_index] = t;}type&pop(){if(!is_empty())--m_top_index;return m_stack_base_ptr[m_top_index + 1];}type&top(){return is_empty() ? m_stack_base_ptr[0] : m_stack_base_ptr[m_top_index];}boolis_full(){return m_top_index >= m_max_element - 1;}boolis_empty(){return m_top_index == -1;}type&at(int idx){return m_stack_base_ptr[idx];}voidclear(){m_top_index = -1;}void destroy(){if (m_stack_base_ptr)delete[]m_stack_base_ptr;m_stack_base_ptr = nullptr;}size_t size(){return m_top_index + 1;}private:type*m_stack_base_ptr = nullptr;intm_top_index = -1;intm_max_element = 0;}; class input_argment{public:input_argment(){}input_argment(double number, bool is_operator = false, char op = '+'){m_number = number;m_is_operator = is_operator;m_operator = op;}doublem_number;boolm_is_operator = false;charm_operator;};boolis_operator(char c, int &priority){bool is_operator = true;switch (c){case '+':case '-':break;case '*':priority = 1;break;case '/':priority = 1;break;case '(':priority = 100;break;case ')':priority = 100;break;default:is_operator = false;break;}return is_operator;}bool is_operator(char c){int p;return is_operator(c, p);}//只看逻辑的话请把对res字符串操作的部分都删了...我看着都恶心std::string reverse_polish(std::string &s){stack<input_argment>  my_stack;my_stack.create_stack(100);std::string res;int idx = 0;char op;for (; idx < s.size(); ++idx){bool is_operator_ = true;int priority = 0;op = s.at(idx);//判断是不是操作符is_operator_ = is_operator(op, priority);res += s.at(idx);//不是操作符就跳过当前循环if (!is_operator_)continue;res.erase(--res.end());//删除输出的操作符 if (res.size()>0&&  res[res.size()-1]!=' ')res += ' ';//栈为空 或者当前的操作符比栈顶操作符的优先级要高或者为(就直接压栈,  )操作符的处理不需要压栈if (my_stack.is_empty() || (!my_stack.is_empty() && my_stack.top().m_number < priority &&op != ')') ||op=='('){my_stack.push(input_argment(priority, true, op));}else {//出栈if (priority == 100) //遇到右括号了{//把(之前的操作符全部出栈while (!my_stack.is_empty()&& my_stack.top().m_operator!='(')res += my_stack.pop().m_operator;my_stack.pop();//(出栈}else  {//把所有优先级大于等于当前操作符的操作符全部出栈 直到遇到优先级更低的操作符或者(while (!my_stack.is_empty() && my_stack.top().m_number >= priority &&my_stack.top().m_number != 100)res += my_stack.pop().m_operator;my_stack.push(input_argment(priority, true, op));//当前操作符压栈}//有时候会出现 1 2 3 * - 这个情况...因为我下面的计算是用空格来分割的,为了方便计算就每次加入一个操作符的时候就看看有没有这样 if (res.size() > 3 && res[res.size() - 2] == ' '&&is_operator(res[res.size() - 1]) &&is_operator(res[res.size() - 3]))res.erase(----res.end());res += ' ';}}if (res[res.size() - 1] == ' ')res.erase(--res.end());else if(!is_operator(res[res.size()-1]))res += ' ';//将剩下的操作符出栈while (!my_stack.is_empty())res += my_stack.pop().m_operator;//去掉多余的空格 auto p = res.find("  ");while ( p!=std::string::npos ){res.erase(res.begin()+p);p = res.find("  ");}return res;}voidconver_notation_to_stack(std::string &s, stack<input_argment> &my_stack){int priority = 0;for (int i = s.size() - 1; i >= 0; --i){if (is_operator(s[i], priority)){my_stack.push(input_argment(0, true, s[i]));}else{std::string res;auto start = s.rfind(' ', i - 1);if (start == std::string::npos)res.assign(s.begin(), s.begin() + i+1);else res.assign(s.begin()+start, s.begin() + i+1);my_stack.push(input_argment(atof(res.data())));if (start == 0)return;elsei = s.rfind(' ',start-1) == std::string::npos ? start+1:start; //判断是不是只剩下一个数字了}}}double calc_res(stack<input_argment> &my_stack){double v1, v2;for (int i = my_stack.size() - 1; i >= 0; --i){if (my_stack.at(i).m_is_operator){ v2 = my_stack.pop().m_number;v1 = my_stack.pop().m_number;switch (my_stack.at(i).m_operator){case '+':my_stack.push(input_argment(v1 + v2));break;case '-':my_stack.push(input_argment(v1 - v2));break;case '*':my_stack.push(input_argment(v1 * v2));break;case '/':my_stack.push(input_argment(v1 / v2));break;}}else{my_stack.push(my_stack.at(i)); }}return my_stack.top().m_number;}int main(){ std::string s,res;s = "1+2+(1+2-3.5+(10*10-(10-20+((30-10)-(1+1.0)+1)-2)+(2-2)+3)-4)+100";stack<input_argment> my_stack;my_stack.create_stack(100);//转化成计算式res = reverse_polish(s);//输出转化的计算公式cout << res.data() << endl;//将转化的计算式字符串转换为数据conver_notation_to_stack(res, my_stack); cout << calc_res(my_stack) << endl;    return 0;}


原创粉丝点击