zoukankan      html  css  js  c++  java
  • Basic Calculator

                                        简单计算器的实现


     一:问题描述:


     写一个简单的计算器,计算一个表达式。

    已知:

    1.用string存储这个表达式。
    2.这个表达式有'(',')','+','-'以及空格和大数运算。
    3.可以认为输入是一定正确的,及不用判断其输入格式。
    输入案例:
    "1 + 1" = 2
    " 2-1 + 2 " = 3
    "(1+(4+5+2)-3)+(6+8)" = 23
    注意: 不得使用eval库.


     二:算法解析


    1.这道题的算法核心是将表达式解析成逆波兰式(或波兰式)以便电脑识别计算,这里将解析为逆波兰式。

    2.大数的加减运算,这里省略。

    注:逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,
    所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级

    解析成逆波兰式的步骤:
    1.先生成s1,s2两个栈,其中s1用来存贮运算符,s2用来存贮解析出的逆波兰式。并且将'#'压入s1栈中,'#'可以用处运算符外任意其他字符替代,其作用是作为一个优先级最小的符号标
    记存贮在s1中,后面的步骤你将看到其作用。
    2.逐个解析string
    3.若x是操作数,则解析出完整的操作数,并将x直接压入栈s2;
     若x是运算符,则分情况讨论:
              若x是'(',则直接压入栈s1;
              若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,并pop掉'(';
              若x是'+或'-'或其他除'('和')'的运算符,则分情况讨论:
                  若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
                  若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,若x的优先级大于栈s1栈顶运算符优先级,则将x直接压入栈s1。否者,
    将栈s1的栈顶运算符弹出,压入栈s2中,直到栈s1的栈顶运算符优先级别低于(不包括等于)x的优先级,或栈s2的栈顶运算符为'(',此时再则将x压入栈s1;
    4.重复2,3操作。
    5.在解析完string后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#')。  
    6.最终s2中就存储了表达式的逆波兰式。


     三:就题论题


    由于这道题不是仅仅求其逆波兰式,而是计算其值。故可如下操作: 

      在解析逆波兰式的过程中,每向栈s2中添加运算符时,判断其是哪个运算符,此时不用再将其添进s2中,而是可以对s2中就接近栈顶的两操作数直接运算,并将两个操作数出栈,将其结果进栈。由于表达式的正确性确定,故在所有操作结束时,s2中仅留下一个操作数,就是其算式的结果,输出即可。


     四:核心代码(栈的构造与解析)


     s1.push('#');

    int length = s.length(), i = 0;
    //转化为数字接受变量
    long long int number = 0;
    bool num = false;
    char ch;

    while(i != length)
    {
    switch(s[i])
    {
    case ' ':
    break;
    case '(':
    //符号前面是否有数字
    if(num)
    {
    s2.push(number);
    num = false;
    number = 0;
    }
    s1.push(s[i]);
    break;
    case ')':
    //符号前面是否有数字
    if(num)
    {
    s2.push(number);
    num = false;
    number = 0;
    }
    while(s1.top() != '(')
    {
    char ch = s1.top();
    //figure
    figure(s2, ch);

    s1.pop();
    }
    s1.pop();
    break;
    case '+':
    case '-':
    //符号前面是否有数字
    if(num)
    {
    s2.push(number);
    num = false;
    number = 0;
    }

    for(ch = s1.top(); ch != '#'; ch = s1.top())
    {
    if(ch == '(')
    {
    break;
    }

    //figure
    figure(s2, ch);
    s1.pop();
    }
    s1.push(s[i]);
    break;
    default:
    //number将字符转换为数字
    number = s[i] - '1' + 1 + number * 10;
    num = true;
    break;
    }
    i++;
    }

    if(num)
    s2.push(number);

    while(s1.top() != '#')
    {
    char ch = s1.top();
    //figure
    figure(s2, ch);

    s1.pop();
    }

    return s2.top();
    }

  • 相关阅读:
    今天是清明节假期的最后一天
    昨天晚上在舅舅家吃饭,得知已经做完肾结石手术
    在今天上午第三节课上完后,下课找了韩请假的事情
    早上把书本和桌子放在一起,下午12:00就要出发
    今天居然在谎称支付宝又返现2元
    今天居然在谎称支付宝又返现2元
    Spring IOP 没用
    面试题:搜狐百度 看1 复杂一点的面试题 笔试题
    项目一:第六天 WebService写接口 和CXF框架
    项目一:第七天 CRM 和bos系统实现定区关联客户,关联快递员. 通过CXF框架实现
  • 原文地址:https://www.cnblogs.com/YJthua-china/p/4921735.html
Copyright © 2011-2022 走看看