7.16总结

本周完成了数据结构小学期第二阶段

完成了lisp算数表达式的计算:功能是输入lisp表达式,完成lisp表达式语法检查,并实现lisp表达式求值。

遇到的问题:表达式语法检查还存在一定问题,只完成了最简单的括号匹配以及特殊字符的判断。

输入next()与nextLine()区别

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("第一次输入");
        String s1 = input.next();
        System.out.println("第二次输入");
        String s2 = input.nextLine();
        System.out.println("第一次输入内容:" + s1 + "\t第二次输入内容:" + s2);
    }
}

运行,输入 1 ,然后回车,发现还没进行第二次输入,系统就开始打印输入内容了

 

如果调换一下顺序,先使用 .nextLine(),在使用 .next(),可以正常录入两次键盘输入

接收内容

next()

1. 不接收空格,只接收有效字符,不能得到一个带空格的字符串

2. next在没有读到有效字符前会把空格、Tab、Enter自动去掉

nextLine()

1. 可以接受空格,能得到带空格的字符串

2. 返回的是Enter之前的一切字符

停止接受

next()在读到有效字符后才会将空格、Tab、Enter视为结束符

nextLine()将Enter视为结束

注意:next()在遇到Enter结束时,并不会吸收Enter; 而nextLine()会吸收Enter。

何谓吸收?
  next()遇到Enter结束,此时键盘录入Enter 的信息仍然停留在内存中, 下次需要输入时,直接读取了该信息。因此本文开头的代码运行时,首先输入1然后回车之后,next()结束,键盘录入Enter的信息没有被吸收,然后被nextLine()吸收并作为结束符。才导致了最后的运行结果。

补充说明
  经过验证,除了nextLine()其他的next的方法,如nextDouble() ,nextFloat() ,nextInt() 等,都无法吸收Enter。

如何解决?
  可以多使用一次nextLine(),用停留在内存中的Enter吸收掉。

 lisp算数表达式代码:

package Dao;

import java.util.Arrays;
import java.util.Scanner;

public class LispTest {

    public static void main(String[] args) throws Exception {
        ArrayStack OPTR = new ArrayStack();
        ArrayStack OPND = new ArrayStack();
        ListEvaluate le = new ListEvaluate();
        le.EvaluateExpression(OPTR, OPND);
        int sum = (int) OPND.GetTop();
        System.out.println("表达式的结果为:" + sum);

    }

}
class  ListEvaluate{
    private final int RIGHT = 1;
    private final int FLASE = 0;
    private static String expression;//表达式
    private static int index=0;//表达式的第 index 个位置
    private static char c; //表达式第index个位置上的对应的字符
    public ListEvaluate() throws Exception {
        int z=0,y=0;
        Scanner in = new Scanner(System.in);
        System.out.println("请输入表达式:");
        expression = in.next();
        expression+="#";
        int length = expression.length();
        for(int i=0;i<length;i++){
            char c = expression.charAt(i);
            String t = String.valueOf(c);
            if("(".equals(t))
                z++;
            else if(")".equals(t))
                y++;
        }
        int a=0;
        if(z==y) {
            for (int i = 0; i < length; i++) {
                char c = expression.charAt(i);
                String t = String.valueOf(c);
                if (isRight(t) == FLASE)
                    throw new Exception("表达式出现不合法字符,请重新输入");
            }
            c = expression.charAt(index);
        }
        else
            throw new Exception("括号不匹配,请重新输入");
    }
    public int isRight(String str){
        if("0".equals(str)||"1".equals(str)||"2".equals(str)||"3".equals(str)||"4".equals(str)||"5".equals(str)||"6".equals(str)||"7".equals(str)||"8".equals(str)||"9".equals(str))
            return RIGHT;
        else if("(".equals(str)||")".equals(str)||"+".equals(str)||"-".equals(str)||"*".equals(str)||"/".equals(str)||"#".equals(str))
            return RIGHT;
        else
            return FLASE;
    }
    public boolean isDight(char c){
        if(c>='0'&&c<='9') return true;
        else return false;
    }
    //计算返回结果
    public int Operate(char x,int a,int b){
        int sum=0;
        switch(x){
            case '+':{sum=a+b;break;}
            case '-':{sum=a-b;break;}
            case '*':{sum=a*b;break;}
            case '/':{sum=a/b;break;}
        }
        return sum;
    }
    public int EvaluateExpression(ArrayStack OPTR,ArrayStack OPND ) throws Exception {
        /*
         * 运用递归的思想,分别计算每个括号的内容
         * OPTR存放运算符,OPND存放数字(或者运算结果)
         * */
        OPTR.Push('#');
        int num=0;//存放从表达式中读取到的数字
        char x; //存放从表达式中读取到的运算符
        while (c!='#'||(char)OPTR.GetTop()!='#'){
            if (c=='('){
                //遇到左括号,开始递归
                c = expression.charAt(++index);//读取表达式的下一个字符
                int sum = EvaluateExpression(new ArrayStack(),new ArrayStack());//递归,返回括号里的运算结果
                OPND.Push(sum);//将运算结果压入数字栈
                if (OPND.StackLength()==2){
                    //果然数字栈长度为2,说明可以进行运算了
                    if ((char)OPTR.GetTop()=='#'){ //如果运算符栈里没有运算符,说明表达式错误
                        throw new Exception("表达式错误");
                    }
                    else{
                        x =(char)OPTR.Pop();
                        int b =(int) OPND.Pop();
                        int a = (int)OPND.Pop();
                        OPND.Push(Operate(x,a,b));//计算 a x b 的结果,并压入结果栈中

                    }
                }

            }
            if (c==')'&&(char)OPTR.GetTop()=='#'){
                //如果读取到右括号,并且运算符栈为空(即栈顶是#号)说明该括号内容计算完毕
                c = expression.charAt(++index);//读取下一个字符
                return (int)OPND.GetTop();//返回运算结果(即栈顶元素)
            }
            if (isDight(c)==true){
                //如果该字符是数字
                num =(int)(c-'0');//char转int
                OPND.Push(num);
                if (OPND.StackLength()==2){
                    //果然数字栈长度为2,说明可以进行运算了
                    if ((char)OPTR.GetTop()=='#'){
                        throw new Exception("表达式错误");
                    }
                    else{
                        x =(char)OPTR.Pop();
                        int b =(int) OPND.Pop();
                        int a = (int)OPND.Pop();
                        OPND.Push(Operate(x,a,b));//计算 a x b 的结果,并压入结果栈中

                    }
                }
                c=expression.charAt(++index);
            }else if (c!='#'&&c!='('&&c!=')'){
                //读取到的字符是运算符
                OPTR.Push(c);
                c=expression.charAt(++index);
            }
        }
        return (int)OPND.GetTop();
    }
}
class   ArrayStack<T> { //栈的相关方法

    private int max_size;//栈的容量
    private T[] array;//栈数组
    private int top;//栈顶指针

    public ArrayStack() { //申请内存空间
        this.max_size = 100;
        array = (T[]) new Object[max_size];
        this.top = -1;
    }

    public ArrayStack(int size) {
        this.max_size = size;
        array = (T[]) new Object[max_size];
        this.top = -1;
    }

    public void Push(T t) { //入栈
        top++;
        if (top > array.length - 1) {
            T[] copy = Arrays.copyOf(array, max_size * 2);
            array = copy;
        }
        array[top] = t;
    }

    public T Pop() throws Exception { //出栈
        if (top >= 0) {
            return array[top--];
        } else {
            throw new Exception("空栈,无法进行出栈操作");
        }
    }

    public T GetTop() throws Exception { //获得栈顶元素
        if (top < 0) throw new Exception("空栈,栈顶为空");
        else return array[top];
    }

    public boolean isEmpty() { //栈的判空
        if (top == -1) return true;
        else return false;
    }
    public int StackLength(){ //返回栈的长度
        return top+1;
    }
}

 

posted @ 2022-07-16 20:17  慢漫曼蔓  阅读(12)  评论(0)    收藏  举报