注册 登录
重磅消息:开通VIP会员,获取平台所有项目,永久使用,详细请咨询QQ:3376762016
远程服务部署安装,售后服务,请加QQ1:3376762016,QQ2:3597230140(即将满员),QQ3:1399491757(已满)
查看: 450|回复: 0
打印 上一主题 下一主题

基于Java控制台实现计算器

[复制链接]

该用户从未签到

3518

主题

3532

帖子

66万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
668954
QQ
跳转到指定楼层
楼主
发表于 2020-9-19 17:37:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


import java.text.DecimalFormat;
import java.util.Scanner;
import java.util.Stack;

/**
* 简单四则运算,支持的运算符有:加减乘除以及小括号,不支持乘方、开方、中括号等运算符
* 算法实现:
* 栈、二叉树、递归
* 算法思路:
* 以)为界,把相邻两个()中的数字和运算符压栈,然后根据栈构造二叉树,最后递归二叉树求出结果。
* 如计算1+2+3
*               +
*              /\
*             3  +
*               /\
*              1  2
*  计算1+(2*3)/2
*
*              +
*             /\
*            1  /
*              /\
*             *  2
*            /\
*           2  3
*/
public class Main {


    public static void main(String[] args) throws Exception {
        Scanner cin = new Scanner(System.in);
        int id = 1;
        System.out.print("请输入表达式:");
        while (cin.hasNext()) {
            String str = cin.next();
            str = str.replaceAll(" +", "");//删除所有空格
            if (!IsExpressionValid(str)) { //检查表达式是否合法
                System.out.print("表达式有误,请重新输入:");
                continue;
            }
            Tools tools = new Tools(str); // 辅助类,把输入的表达式传进入
            double ans = tools.toValue();
            DecimalFormat df = new DecimalFormat("#");
            System.out.println(str + "=" + (ans % 1 == 0 ? df.format(ans) : ans));
            System.out.print("请输入表达式:");
        }
    }

    public static boolean IsExpressionValid(String str) {
        /**
         * 开头不能有 + * / )
         * 结尾不能有 + - * / (
         * 不能出现连续两个运算符
         * 不能出现非法字符
         * 不能出现 *) 的情况
         */
        String regex = "(^[+\\-*-/).].*)|(.*[+\\-*-/(.]$)|(.*[+\\-*/]{2,}.*)|(.*\\(\\)+.*)|(.*[^+\\-*/.()0-9].*)|(.*[+\\-*/]\\).*)";

        if (str.matches(regex)) {
            return false;
        }
        Stack<Character> stk = new Stack<>(); //检测括号是否匹配,比如不能出现 (1 + 2)*6)) 的情况

        boolean flag = true;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '(') {
                stk.push(str.charAt(i));
            } else if (str.charAt(i) == ')') {
                if (stk.empty()) {
                    flag = false;
                    break;
                }
                stk.pop();
            }
        }
        return flag && stk.empty();
    }
}

class Tools extends Tree { // 辅助类
    char[] ch; // 存放输入
    String str;//和ch[]存放同一个输入
    int i;

    public Tools(String str) {
        super();
        this.str = str;
        this.ch = str.toCharArray(); // 把传进来的String转为字符串
        this.root = work();
    }

    public BinaryNode work() { // 对串进行判断,分括号、乘除、加减以及数字或字母 三大部分
        Stack<BinaryNode> st = new Stack<BinaryNode>();
        while (i < this.ch.length) { // 一切建立在ch[]范围内才执行
            double num = 0;
            boolean flag = false;
            int j = i;
            while (i < this.ch.length && ((ch[i] >= '0' && ch[i] <= '9') || ch[i] == '.')) { // 加入数字判断
                i++;
                flag = true;
            }
            if (flag) {
                String tmp = String.valueOf(ch).substring(j, i);
                num = Double.parseDouble(tmp);
                st.push(new BinaryNode(String.valueOf(num))); // 如果是数字单独处理
                continue;
            }
            if (ch[i] == '(') { // 左括号,把括号内当成一整个部分入栈
                i++;
                st.push(work());
            } else if (ch[i] == ')') { // 遇到右括号,结束循环自然返回刚进行的栈结果
                break;
            } else if ((ch[i] == '*' || ch[i] == '/') && ch[i + 1] != '(') {
                flag = false;
                int k = i + 1;
                while (k < this.ch.length && ((ch[k] >= '0' && ch[k] <= '9') || ch[k] == '.')) { // 加入数字判断
                    k++;
                    flag = true;
                }
                BinaryNode bn = null;
                if (flag) {
                    String tmp = String.valueOf(ch).substring(i + 1, k);
                    num = Double.parseDouble(tmp);

                    bn = new BinaryNode(String.valueOf(ch[i]), st.pop(),
                            new BinaryNode(String.valueOf(num)));
                    i = k - 1;
                } else {
                    bn = new BinaryNode(String.valueOf(ch[i]), st.pop(),
                            new BinaryNode(String.valueOf(ch[++i])));
                }
                st.push(bn);
            } else {// +或-
                st.push(new BinaryNode(String.valueOf(ch[i])));
            }
            i++;
        }
        return creattree(st); // 把运算的栈传入creattree返回树结构
    }

    public BinaryNode creattree(Stack<BinaryNode> stack) { // 对传进来的栈分离,返回树结构
        Stack<BinaryNode> t = new Stack<BinaryNode>(); // 倒置栈内元素
        BinaryNode bn = null;
        int k = 0;
        if (stack.size() == 1) {
            return stack.peek();
            /**-
             * 传进来已经是树结构,当只有一个时,直接返回, 如(a+b) 传进来已经是 +
             * 这个数结构,直接返回就可以 a b
             */
        }
        while (!stack.empty()) {
            t.push(stack.pop()); // 栈为原来的倒序,转为正序
        }
        while (!t.isEmpty()) {
            if (t.size() < 3) // 输入表达式有错误,如只输入 a+ 这个不完整的表达式
                break;

            BinaryNode left = t.pop(); // 按顺序循环取出树结构
            BinaryNode root = t.pop();
            BinaryNode right = t.pop();

            bn = new BinaryNode(root.data, left, right);

            if (!t.isEmpty()) { // 如果栈里不为空,表示还有节点,将创建的bn节点再放进栈里
                t.push(bn);
            } else {
                break; // 否则退出,此时树结构已经存放在bn
            }
        }
        return bn;
    }

    public double toValue() {
        return this.toValue(this.root);
    }

    public double toValue(BinaryNode p) {
        double num = 0;
        if (p == null)
            return 0;
        if (!p.isLeaf()) {
            switch (p.data.charAt(0)) {
                case '+':
                    num = toValue(p.left) + toValue(p.right);
                    break;
                case '-':
                    num = toValue(p.left) - toValue(p.right);
                    break;
                case '*':
                    num = toValue(p.left) * toValue(p.right);
                    break;
                case '/':
                    num = toValue(p.left) / toValue(p.right);
                    break;
            }
            return num;
        }
        return Double.parseDouble(p.data);
    }
}

class Tree { // 二叉树类
    BinaryNode root;

    public Tree(BinaryNode root) {
        super();
        this.root = root;
    }

    public Tree() {
        super();
        this.root = null;
    }

}

class BinaryNode // 二叉树的二叉链表结点类
{
    public String data; // char类型的数据
    public BinaryNode left, right; // 左右分支

    public BinaryNode(String data, BinaryNode left, BinaryNode right) { // 放入数据,并放入左右分支
        this.data = data;
        this.left = left;
        this.right = right;
    }

    public BinaryNode(String data) { // 放入数据,左右分支为空
        this(data, null, null);
    }

    public boolean isLeaf() {
        return this.left == null && this.right == null;
    }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
java无忧网(http://www.javawyw.com),专业提供Java大作业,小作业,课程设计,毕业设计源码,答辩辅导,作业排错,bug修复,专业解答,远程部署运行项目等服务
本网站所有源码,保证能运行!
QQ:1399491757
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回列表 返回顶部