计算器

使用Java写的一个可以计算+,-,*,/ 的计算器。首先用栈把中缀表达式转化成后缀表达式,再利用栈对后缀表达式求值。大致思路就是这样代码看下面


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

/**
 * 思路:首先把中缀表达式转成 后缀表达式 利用后缀表达式求值
 * 
 *
 */
public class Calputer {

    // 把中缀表达式转换为后缀表达式
    public String translateStr(String str) {
        StringBuffer buffer = new StringBuffer();
        int len = str.length();
        Character topChar;
        Stack<Character> stack = new Stack<Character>();
        int count = 0;                                      // 数字位数计数器, 用来区别是多位数字还是一位数字
        for (int i = 0; i < len; i++) {
            boolean flag = false;                           // 运算符出栈时使用,作为循环条件使用, 栈顶元素优先级小于nextChar的标志
            Character nextChar = str.charAt(i);
            if (isDigit(nextChar)) {
                if (count == 0) {                           // 每个数字在输出时在前面添加一个空格
                    buffer.append(" ");
                }
                buffer.append(nextChar);
                count++;
            } else {
                switch (nextChar) {
                case '+':
                case '-':
                case '*':
                case '/':
                    while (!flag && !stack.empty()) {       // 循环比较nextChar和topChar的优先级
                        topChar = stack.peek();             // 先取出栈顶元素
                        if (getPre(nextChar) <= getPre(topChar)) { // 比较优先级, 如果栈顶元素的优先级大于nextChar就出栈
                            buffer.append(" ");
                            buffer.append(topChar);         // 把栈顶元素添加到字符串
                            stack.pop();                    // 出栈
                        } else {                            // 如果栈顶元素优先级小于nextChar的优先级,就结束while循环,则nextChar进栈
                            flag = true;                    // 把flag设为true,结束循环
                        }
                    } // end while()
                    stack.push(nextChar);                   // 进栈
                    break;

                case '(':                                   // 遇到'('直接进栈
                    stack.push(nextChar);
                    break;

                case ')':                                   // 遇到')' 就要循环出栈, 直到遇到'('时结束循环
                    topChar = stack.pop();                  // 首先弹出栈顶的元素
                    while (topChar != '(') {                // 开始循环出栈直到遇到'('结束
                        buffer.append(" ");
                        buffer.append(topChar);
                        topChar = stack.pop();              // 出栈
                    }
                    break;

                default:
                    break;
                } // end switch()
                count = 0;                                  // else语句块执行完毕把计数器归零
            } // end else
        } // end for()
        while (!stack.empty()) {
            topChar = stack.pop();
            buffer.append(" ");
            buffer.append(topChar);
        } // end while()
        return buffer.toString();
    }

    // 获取运算符优先级
    public int getPre(Character c) {
        switch (c) {
        case '(':
        case ')':
            return 0;
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        }
        return -1;
    }

    // 输入检查
    public boolean checkStr(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (Character.isLetter(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    // 是否为数字
    public boolean isDigit(char str) {
        return Character.isDigit(str);
    }

    // 处理后缀表达式,并计算结果
    public int Solution(String str1) {
        Stack<Character> stack = new Stack<Character>();
        String str = translateStr(str1);
        // System.out.println(str);
        String[] arr = str.split(" ");
        // arr里面存在一些空字符串,所以用了个list集合过滤一下
        List<String> list = new ArrayList<String>();
        for (String s : arr) {
            if (!s.equals("")) {
                list.add(s);
            }
        }

        int result = 0;
        Character nextChar;
        for (String s : list) {                                 // 遍历集合, 计算后缀表达式
            if (isDigit(s.charAt(0))) {                         // 根据集合中元素的首字符来判断是数字还是运算符
                nextChar = (char) ((int)Integer.valueOf(s));    // 需要把字符串类型的数字转成char类型压入栈
                stack.push(nextChar);                           // 让数字进栈
            } else {                                            // 如果是运算符
                nextChar = s.charAt(0);
                int right = (int) (stack.pop());                // 从栈中弹出两个数字
                int left = (int) (stack.pop());
                int res = getResult(right, left, nextChar);     // 对弹出的数字进行运算, 运算符为nextChar
                Character newChar = (char) (res);               // 把结果转为char再进栈
                stack.push(newChar);
            }
        }
        result = (int) (stack.pop());                           // list遍历结束, 此时栈中只有一个元素, 就是计算结果, 出栈
        return result;
    }

    // 计算两个数字的运算结果
    private int getResult(int rightNum, int leftNum, Character nextChar) {
        int result = 0;
        switch (nextChar) {
        case '+':
            result = leftNum + rightNum;
            break;
        case '-':
            result = leftNum - rightNum;
            break;
        case '*':
            result = leftNum * rightNum;
            break;
        case '/':
            result = leftNum / rightNum;
            break;
        default:
            break;
        }
        return result;
    }

    public static void main(String[] args) {
        Calputer calputer = new Calputer();
        Scanner scan = new Scanner(System.in);
        while (true) {
            System.out.print("In: ");
            str = scan.nextLine();
            if (!calputer.checkStr(str)) {
                System.out.println("Connot include English character.");
                continue;
            }
            try {
                int res = calputer.Solution(str);
                System.out.println("Out: " + res);
            } catch (Exception e) {
                System.out.println("FormatError.");
                continue;
            }
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Demo戳这里 11月27日更新 使用 switch 语句代替 if 语句,使逻辑更清晰,代码更新部分如下: 原文...
    少年vv阅读 2,537评论 4 0
  • 这些是C/C++能做的 服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入...
    小辰带你看世界阅读 676评论 0 1
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,175评论 1 32
  • 活在当下,原来是一个十分无奈的词。 我们无法决定之后也无法改变过去。除了活在当下我们无计可施。 时间的快慢,相比较...
    杏林医者Dr张阅读 578评论 2 2
  • 今天在得到知识新闻工作室,听了施伟教授在“中国人民大学商学院2017新年论坛”上的演讲,2017年企业转型的六大方...
    严贤平1阅读 447评论 0 0