首页 > 代码库 > 混和运算

混和运算

用计算器比较麻烦,因为它不按计算顺序来,需要按很多次(加之平时用得少,又掺进来负数,按上十来次就按错了)。出于统计方便,写了个程序专门算数。

效果如下(格式不作要求,只要输对就行):





主要代码:

/*///////////////////////////////////////

带括号的四则运算:

-------------------------------------
1、中序转为后序表达式
顺序读取,对不同对象按不同情况处理:

1)运算数:直接输出
2)左括号:压入堆栈
3)右括号:将栈的运算符弹出并输出,直到遇到左括号(弹出,不输出)
4)运算符:
若优先级大于栈顶运算符,则把它压栈
若优先级小于等于栈顶运算符,将栈顶运算符弹出并输出,再比较新的栈顶运算符,
直到该运算符优先级大于栈顶运算符为止,然后将该运算符压栈
5)若所有对象处理完毕,则把堆栈中残留的运算符一并输出

--------------------------------------
2、计算后序表达式
每遇到运算符则对它之前的两个数计算

--------------------------------------
程序支持形如 -0.3 + 4 * (-1.5 + -6.4 / -2) * -4 形式的算式

////////////////////////////////////////*/
#include "LinkedStack.h"
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

string Calculate(char oper, double a, double b)
{
    switch(oper)
    {
    case '+':a += b; break;
    case '-':a -= b; break;
    case '*':a *= b; break;
    case '/':
         if(b != 0) 
             a /= b;
         else
             throw BadInput();
    }
    stringstream stream;
    stream << a;
    string str;
    stream >> str;
    return str;
}



// 删除字符串中空格
void trim(string &str, string::size_type pos = 0)
{
    static const string delim = " \t"; //删除空格或者tab字符
    pos = str.find_first_of(delim, pos);

    if(pos == string::npos)
        return;

    trim(str.erase(pos, 1));
}

// 从某处起略过数字添加右括号
void AddRight(string& line, int i)
{
    int len = line.length();
    ++i;
    while(i < len && (line[i] == '0' || line[i] == '1' ||
        line[i] == '2' || line[i] == '3' || line[i] == '4' ||
        line[i] == '5' || line[i] == '6' || line[i] == '7' ||
        line[i] == '8' || line[i] == '9' || line[i] == '.'))
        ++i;
    line.insert(i, ")");
}


// 处理负数和正号
string&  HandleExp(string& line)
{
    trim(line);

    if(line[0] == '-' || line[0] == '+')
    {
        AddRight(line, 0);  // 先补右括号
        line = "(0" + line; // 再补左括号
    }        
    
    // 需用 line.length(),因为长度不断在变化
    for(unsigned i = 1; i < line.length(); ++i) 
    {
        if(( line[i] == '-' || line[i] == '+') &&    
           ( line[i - 1] == '+' || line[i - 1] == '-' || 
             line[i - 1] == '*' || line[i - 1] == '/' ||
             line[i - 1] == '(' ))
        {
            AddRight(line, i); // 先补右括号
            line = line.insert(i, "(0");
        }
    }
    return line;
}


// 处理表达式,并将中序转后序表达式,并进行计算
string InToPost(string& line)
{
    line = HandleExp(line);

    LinkedStack<string>num;
    LinkedStack<char>symb;
  
    char op;
    double a,b;
    int size = line.length(), i;
    string item("");
  
    for(i = 0; i < size; ++i)
    {        
        if(line[i] == '(')
        {
            symb.Add('(');
            continue;
        }
        if(line[i] == '*' || line[i] == '/')
        {
            if(item != "")
            {
                num.Add(item);
                item = "";
            }

            if( !symb.IsEmpty() && symb.Top() != '('
                &&(symb.Top() == '*' || symb.Top() == '/'))
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add( Calculate(op, a, b) );
                item = "";
            }
            symb.Add(line[i]);
            continue;
        }

        if(line[i] == '+' || line[i] == '-')
        {       
            if(item != "")
            {
                num.Add(item);
                item = "";
            }

            if(!symb.IsEmpty() && symb.Top() != '(' )
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add(Calculate(op, a, b));
                item = "";
            }
            symb.Add(line[i]);
            continue;
        }
        if(line[i] == ')')
        {
            if(item != "")
            {
                num.Add(item);
                item = "";
            }
            while(!symb.IsEmpty() && symb.Top() != '(')
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add(Calculate(op, a, b));
            }
            symb.Delete(op); // 删除 (
            item = "";
            continue;
        }
        else
        {
            item += line[i];
        }
    }

    // 最后一个数字
    if(item != "")
    {
        num.Add(item);       
        item = "";
    }

    while(!symb.IsEmpty())
    {
        symb.Delete(op);
        num.Delete(item);
        b = strtod(item.c_str(), NULL);
        num.Delete(item);
        a = strtod(item.c_str(), NULL);
        num.Add(Calculate(op, a, b));
    }

    return num.Top();
}


混和运算