java实现简单计算器(不带界面、控制台输入输出),代码注释很多

废话不多说,直接上代码
主类:Main.java

import java.util.Scanner;
/*
*
* 可能这个程序有很多不必要的步骤,必须为啥不把下面两个方法写在一个main方法中,
* 在这解释一下,这是为了后期好在里面添加一些我们需要的东西,便于维护
* 虽然只是一个小项目,但是养成习惯是好多(或许我现在还年轻,陷入误区,希望自行思考)
*
* 多谢多谢,勿喷
*
* */
public class Main {
    public static void main(String[] args) {
        String str = getInputExpression();
        run(str);
    }
    //获取输入的中缀表达式
    public static String getInputExpression(){
        System.out.println("请输入表达式:该表达式不能计算负数,");
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        return str;
    }
    //开始计算,计算结果直接输入
    public static void run(String str){
        Calcutor calcutor = new Calcutor(str);
        if(calcutor.checkStr()){
            String result = calcutor.calResult();
            System.out.println(result);
            return ;
        }else{
            return ;
        }
    }
}

Calcutor.java

import java.util.ArrayList;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
* 该计算不包含负数运算
* 此段代码中命名自我感觉不怎么规范,但是能力有限,实在没什么经验,不晓得怎么改比较好
* 经验不足
* */
public class Calcutor {
    private String inputString;

    public Calcutor() {
    }

    public Calcutor(String inputString) {
        this.inputString = inputString;
    }

    public String getInputString() {
        return inputString;
    }

    public void setInputString(String inputString) {
        this.inputString = inputString;
    }
    //将中缀表达式转化为后缀表达式,返回类型为字符串
    public ArrayList<String> changeSuffix(){
        Stack<Character> operatorStack = new Stack();           //存放操作数的栈
        ArrayList<String> resultStr = new ArrayList<>();         //存放结果的字符串数组
        String str = this.inputString;                          //得到输入的中缀表达式
        String numStr = "";                                     //  遍历中缀表达式是存放每一个数的字符串
        int i = 0;                                              //遍历中缀时的下表
        char nowChar = str.charAt(i);                           //得到具体每一个字符
        operatorStack.push('=');                            //将栈底等于‘=’
        while(nowChar != '=' || !(operatorStack.peek() == '=')){    //循环遍历,
            nowChar = str.charAt(i);
            //如果此时字符为0-9或者是小数点
            if(nowChar >= '0' && nowChar <= '9' || nowChar == '.'){
                //记录每一个数,并保存在numStr中
                while(nowChar >= '0' && nowChar <= '9' || nowChar == '.'){
                    numStr += nowChar;
                    i ++;
                    nowChar = str.charAt(i);
                }
                //将数入栈
                resultStr.add(numStr);
                //制空,便于下次使用
                numStr = "";
                //字符为+-
            }else if(nowChar == '+' || nowChar == '-'){
                //此时判断优先级,在栈顶如果是+-*/,则将前面的出栈,并将现在的操作符入栈,循环的作用是为了连续出栈
                while(operatorStack.peek() == '*' || operatorStack.peek() == '/' || operatorStack.peek() == '+' || operatorStack.peek() == '-' ){
                    String temp = String.valueOf(operatorStack.pop());
                    resultStr.add(temp);
                }
                operatorStack.push(nowChar);
                i ++;
                //如果此时为操作符
            }else if(nowChar == '*' || nowChar == '/'){
                while(operatorStack.peek() == '*' || operatorStack.peek() == '/'){
                    String temp = String.valueOf(operatorStack.pop());
                    resultStr.add(temp);
                }
                operatorStack.push(nowChar);
                i ++;
                //(入栈,什么都不用做
            }else if(nowChar == '('){
                operatorStack.push(nowChar);
                i ++;
                //)将操作符栈顶出栈,知道遇到了(
            }else if(nowChar == ')'){
                while(operatorStack.peek() != '('){
                    String temp = String.valueOf(operatorStack.pop());
                    resultStr.add(temp);
                }
                i ++;
                operatorStack.pop();
                //这里默认中缀结束符为 = ,如果栈中只有'=',那么结束,成功转化
            }else if(nowChar == '=' && operatorStack.peek() != '='){
                i = str.length()-1;
                while(operatorStack.peek() != '='){
                    String temp = String.valueOf(operatorStack.pop());
                    resultStr.add(temp);
                }
                //避免以后还有情况,预留一个else,此时为空
            }else{

            }
        }
        return resultStr;
    }

    //计算后缀表达式
    public String calResult(){
        String result = "";                                 //记录结果
        Stack<String> strStack = new Stack<>();             //将数字入栈
        ArrayList<String> list = changeSuffix();            //得到后缀表达式
        int i = 0;                                          //下标,用于遍历后缀表达式
        while(i <list.size()){
            //如果是操作符,就将栈顶头两个出栈,进行计算,将计算后的结果入栈,然后重复操作
            if(list.get(i).equals("+") || list.get(i).equals("-") || list.get(i).equals("*") || list.get(i).equals("/")){
                double numLastToOne = Double.parseDouble(strStack.pop());
                double numLastToTwo = Double.parseDouble(strStack.pop());
                double operatorResult = cal(numLastToTwo,numLastToOne,list.get(i).charAt(0));
                strStack.push(String.valueOf(operatorResult));
            }else{              //如果是数字,入栈,等待计算
                strStack.push(list.get(i));
            }
            i ++;
        }
        result = strStack.pop();
        return result;
    }

    //简单四则运算
    public double cal(double paramsOne,double paramsTwo, char symbol){
        double result = 0;
        switch (symbol){
            case '+':{
                result = paramsOne + paramsTwo;
                break;
            }
            case '-':{
                result = paramsOne - paramsTwo;
                break;
            }
            case '*':{
                result = paramsOne * paramsTwo;
                break;
            }
            case '/':{
                result = paramsOne / paramsTwo;
                break;
            }
        }
        //结果保留两位有效数字
        return Double.parseDouble(String.format("%.2f",result));
    }

    //检查字符串是否合格
    public boolean checkStr(){
        String str = this.inputString;
        if(!(illegalCharacter(str) || continuousOperator(str) || exceptZero(str) || emptyBrackets(str))){
            return true;
        }else{
            return false;
        }
    }
    //非法字符
    public boolean illegalCharacter(String str){
        //利用正则判断是否存在,后面一样
        String exp = "[^0-9\\.\\+\\*\\-/=\\(\\)]";
        Pattern pattern = Pattern.compile(exp);
        Matcher matcher = pattern.matcher(str);

        if(matcher.find()){
            System.out.println("存在非法字符");
            return true;
        }else{
            return false;
        }
    }
    //连续操作符
    public boolean continuousOperator(String str){
        String exp = "[=\\+\\-\\*/]{2,}";
        Pattern pattern = Pattern.compile(exp);
        Matcher matcher = pattern.matcher(str);
        if(matcher.find()){
            System.out.println("存在连续操作符");
            return true;
        }else{
            return false;
        }
    }
    //除0操作
    public boolean exceptZero(String str){
        String exp = "/0";
        Pattern pattern = Pattern.compile(exp);
        Matcher matcher = pattern.matcher(str);
        if(matcher.find()){
            System.out.println("存在除0操作");
            return true;
        }else{
            return false;
        }
    }
    //检查是否有空括号
    public boolean emptyBrackets(String str){
        String exp = "\\(\\)";
        Pattern pattern = Pattern.compile(exp);
        Matcher matcher = pattern.matcher(str);
        if(matcher.find()){
            System.out.println("存在空括号");
            return true;
        }else{
            return false;
        }
    }
}

计算器的主要编程思想是想办法将中缀表达式转化为后缀表达式,便于计算
写之前可以先去了解一下中转后的思想,事半功倍

你可能感兴趣的:(java)