数据结构:项目三、算术表达式求解

一、问题描述及基本要求

【问题描述】
设计一个简单的算术表达式计算器。
【基本要求】
 实现标准整数类型的四则运算表达式的求值(包含括号,可多层嵌入).
【测试数据】
(30+2*70)/3-12*3
 5+(9*(62-37)+15)*6
 要求自行设计非法表达式,进行程序测试,以保证程序的稳定运行。
【实现提示】
可以设计以下辅助函数
status isNumber(char ReadInChar);//视ReadInchar 是否是数字而返回 TRUE 或 FALSE 。
int TurnToInteger(char IntChar);   // 将字符’0’.’9’ 转换为整数 9

二、问题分析和任务定义

1. 以字符列的形式从终端输入语法正确的、不含变量的整数表达式。利用已知的算符优先关系,实现对算术四则混合运算表达式的求值,并仿照教科书的例子在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。

2. 一般来说,计算机解决一个具体问题时,需要经过几个步骤:首先要从具体问题抽象出一个适当的数学模型,然后设计一个解决此数学模型的算法,最后编出程序,进行测试,调试直至得到想要的答案。对于算术表达式这个程序,主要利用栈,把运算的先后步骤进行分析并实现简单的运算!为实现算符优先算法,可以使用两个栈,一个用以寄存运算符,另一个用以寄存操作数和运算结果。

3. 演示程序是以用户于计算机的对话方式执行,这需要一个模块来完成使用者与计算机语言的转化。

4. 程序执行时的命令:本程序为了使用具体,采用菜单式的方式来完成程序的演示,几乎不用输入什么特殊的命令,只需按提示输入表达式即可。(要注意输入时格式,否者可能会引起一些错误)

5. 测试数据。

三、实验代码

package E3;

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

public class test {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        //System.out.println(s.substring(1));
        calculate(s);
    }
    //负数的问题
    public static int calculate(String strExpression)
    {
        String s = simplify(strExpression);
        System.out.println("s : "+s);
        String numStr = "";//记录数字
        Stack<Character> opeStack = new Stack<>();//符号站
        int l = s.length();//字符串长度 l
        List<String> list = new ArrayList<>();

        for(int i=0;i<l;i++)
        {
            char ch = s.charAt(i);

            if(isAllOpe(ch))
            {
                if(numStr!="")
                {
                    list.add(numStr);
                    numStr="";
                }


                if(ch=='(')
                {
                    opeStack.push(ch);
                }
                else if(isOpe(ch))
                {
                    char top = opeStack.peek();
                    if(isGreater(ch, top))
                    // ch优先级大于top 压栈
                    {
                        opeStack.push(ch);
                    }
                    else
                    //否则,将栈内元素出栈,直到遇见 '(' 然后将ch压栈
                    {
                        while(true)
                        //必须先判断一下 后出栈 否则会有空栈异常
                        {
                            char t=opeStack.peek();
                            if(t=='(')
                                break;
                            if(isGreater(ch, t))
                                break;

                            list.add(Character.toString(t));
                            t=opeStack.pop();
                        }
                        opeStack.push(ch);

                    }

                }
                else if(ch==')')
                {
                    char t = opeStack.pop();
                    while(t!='('&&!opeStack.isEmpty())
                    {
                        list.add(Character.toString(t));
                        t = opeStack.pop();
                    }
                }

            }
            else//处理数字
            {
                numStr+=ch;
            }
        }

        //计算后缀表达式
        System.out.println(list.toString());
        Stack<Integer> num = new Stack<>();
        int size = list.size();
        for(int i=0;i<size;i++)
        {
            String t =list.get(i);
            if(isNumeric(t))
            {//将t转换成int 方便计算
                num.push(Integer.parseInt(t));
            }
            else
            {
                //如果t为运算符则 只有一位
                char c = t.charAt(0);
                int b = num.pop();
                //如果有 算式是类似于 -8-8 这样的需要判断一下栈是否为空
                int a = num.pop();
                switch(c)
                {
                    case '+':
                        num.push(a+b);
                        break;
                    case '-':
                        num.push(a-b);
                        break;
                    case '*':
                        num.push(a*b);
                        break;
                    case '/':
                        num.push(a/b);
                        break;
                    default:
                        break;
                }
            }
        }
        System.out.println(num.pop());
        return 0;
    }


    /**化简表达式
     * 将表达式中的 {}[]替换为()
     * 负数的处理
     * 为了方便将中缀转换为后缀在字符串前后分别加上(,) eg:"1+1" 变为"(1+1)"
     * @param str 输入的字符串
     * @return s 返回简化完的表达式
     */
    public static String simplify(String str)
    {
        //负数的处理
        // 处理负数,这里在-前面的位置加入一个0,如-4变为0-4,
        // 细节:注意-开头的地方前面一定不能是数字或者反括号,如9-0,(3-4)-5,这里地方是不能加0的
        // 它的后面可以是数字或者正括号,如-9=>0-9, -(3*3)=>0-(3*3)
        String s = str.replaceAll("(?<![0-9)}\\]])(?=-[0-9({\\[])", "0");
        //将表达式中的 {}[]替换为()
        s = s.replace('[', '(');
        s = s.replace('{', '(');
        s = s.replace(']', ')');
        s = s.replace(']', ')');
        //为了方便将中缀转换为后缀在字符串前后分别加上(,)
        s="("+s+")";

        return s ;
    }

    /**判断字符c是否为合理的运算符
     *
     * @param c
     * @return
     */
    public static boolean isOpe(char c)
    {
        if(c=='+'||c=='-'||c=='*'||c=='/')
            return true;
        else
            return false;
    }

    public static boolean isAllOpe(char c)
    {
        if(c=='+'||c=='-'||c=='*'||c=='/')
            return true;

        else if(c=='('||c==')')
            return true;
        else
            return false;
    }

    /**
     * 比较字符等级a是否大于b
     * @param a
     * @param b
     * @return 大于返回true 小于等于返回false
     */
    public static boolean isGreater(char a,char b)
    {
        int a1 = getLevel(a);
        int b1 = getLevel(b);
        if(a1>b1)
            return true;
        else
            return false;
    }

    /**
     * 得到一个字符的优先级
     * @param a
     * @return
     */
    public static int getLevel(char a)
    {

        if(a=='+')
            return 0;
        else if(a=='-')
            return 1;
        else if(a=='*')
            return 3;
        else if(a=='/')
            return 4;
        else
            return -1;

    }

    //判断是不是数字
    public static boolean isNumeric(String str){
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if( !isNum.matches() ){
            return false;
        }
        return true;
    }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值