0

所以我正在尝试实现一个调车场来与 Logic 一起工作,我认为这会很容易,直到我遇到为物质条件(->)和双条件(​​<->)设置优先级的问题语句,因为它们需要表示为字符串而不是字符。我需要能够读取带有诸如(A|B) -> !C(这意味着:(A OR B)暗示NOT C)之类的语句的文件并将其转换为后缀表示法。我在第 115 行不断收到 NullPointerException,实际上我不确定为什么,我只能使用 char 值设置案例吗?或者我是否需要找到另一种设置符号优先级的方法。这是我的代码

import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Scanner;
import java.io.File;
import java.util.ArrayList;
import java.io.Reader;

public class ShuntingYard
{

public static ArrayList<String> symbols = new ArrayList<String>();
public static ArrayList<String> letters = new ArrayList<String>();
public static String path = "";
public static void main(String args[])
{
    ShuntingYard sy = new ShuntingYard();

    //Scans in File.
    Scanner scan = new Scanner(System.in);
    String prompt = "Please specify the file path.\n Use the form: D:\\DiscreteMath\\inputFile.txt";
    System.out.println(prompt);
    path = scan.next();
    File file = new File(path);
    String infix = "";

    try{

        scan = new Scanner(file);
        infix = scan.nextLine();

    }
    catch(IOException e)
    {
        System.err.println(" No file");
    }
    // calls postfix function
    String postfix = sy.postfix(infix);
    System.out.println("\nPostfix expression : " + postfix);
    String al = "A,B,C,D,E,";

}
public enum Precedence 
{
    //configure precedence of symbols and operands.
    lparen(0), rparen(1), not(2), and(3), or(4), mc(5), bc(6), eos(7), operand(8);

    private int index;
    Precedence(int index)
    {
        this.index = index;
    }
    public int getIndex()
    {
        return index;
    }
}
private static final int[] isp = {0,19,12,12,13,13,0};
private static final int[] icp = {20,19,12,12,13,13,0};
private static final String[] operators = {"{","}","!","&","|","->","<->"," "};

//initializes stack
private Precedence[] stack;

private int top;

private Precedence pop()
{
    return stack[top--];
}
private void push(Precedence ele)
{
    stack[++top] = ele;
}
//Sets Precedence of symbols.
public Precedence getToken(String symbol)
{
    switch(symbol)
    {
        case "(" : return Precedence.lparen;
        case ")" : return Precedence.rparen;
        case "!" : return Precedence.not;
        case "&" : return Precedence.and;
        case "|" : return Precedence.or;
        case "->" : return Precedence.mc;
        case "<->" : return Precedence.bc;
        case " " : return Precedence.eos;
        default : return Precedence.operand;
    }
}
//Changes infix to postfix notation then returns a string value.
public String postfix(String infix)
{
    String postfix = ""; 
    top = 0;
    stack = new Precedence[infix.length()];
    Precedence token;
    for(int i = 0; i<infix.length(); i++)
    {
        token = getToken(Character.toString(infix.charAt(i)));

        if(token == Precedence.operand)
        {
            postfix = postfix + infix.charAt(i);
        }
        else if(token == Precedence.rparen)
        {
            while(stack[top] != Precedence.lparen)
            {
                postfix = postfix + operators[pop().getIndex()];
            }
            pop();
        }
        else
        {
            while(isp[stack[top].getIndex()] >= icp[token.getIndex()])
            {
                postfix = postfix + operators[pop().getIndex()];
            }
            push(token);
        }
    }
    while((token = pop()) != Precedence.eos)
    {
        postfix = postfix + operators[token.getIndex()];
    }
    return postfix;
}

}

4

1 回答 1

0

问题是您没有检查空堆栈。如果您在两个地方添加对空堆栈的检查,则代码可以工作。

import java.util.ArrayList;
import java.util.Arrays;

public class ShuntingYard
{

public static ArrayList<String> symbols = new ArrayList<String>();
public static ArrayList<String> letters = new ArrayList<String>();
public static String path = "";
public static void main(String args[])
{
    ShuntingYard sy = new ShuntingYard();

    //Scans in File.
//    Scanner scan = new Scanner(System.in);
//    String prompt = "Please specify the file path.\n Use the form: D:\\DiscreteMath\\inputFile.txt";
//    System.out.println(prompt);
//    path = scan.next();
//    File file = new File(path);
    String infix = "(A|B)&C"; //    String infix = "(A|B) -> !C";

//    try{
//
//        scan = new Scanner(file);
//        infix = scan.nextLine();
//
//    }
//    catch(IOException e)
//    {
//        System.err.println(" No file");
//    }
    // calls postfix function
    String postfix = sy.postfix(infix);
    System.out.println("\nPostfix expression : " + postfix);
    String al = "A,B,C,D,E,";
    // line 38
}
public enum Precedence 
{
    //configure precedence of symbols and operands.
    lparen(0), rparen(1), not(2), and(3), or(4), mc(5), bc(6), eos(7), operand(8);

    private int index;
    Precedence(int index)
    {
        this.index = index;
    }
    public int getIndex()
    {
        return index;
    }
}
private static final int[] isp = {0,19,12,12,13,13,0};
private static final int[] icp = {20,19,12,12,13,13,0};
private static final String[] operators = {"{","}","!","&","|","->","<->"," "};

//initializes stack
private Precedence[] stack;

private int top;

private Precedence pop()
{
    return stack[top--];
}
private void push(Precedence ele)
{
    stack[++top] = ele;
}
//Sets Precedence of symbols.
public Precedence getToken(String symbol)
{
    switch(symbol)
    {
        case "(" : return Precedence.lparen;
        case ")" : return Precedence.rparen;
        case "!" : return Precedence.not;
        case "&" : return Precedence.and;
        case "|" : return Precedence.or;
        case "->" : return Precedence.mc;
        case "<->" : return Precedence.bc;
        case " " : return Precedence.eos;
        default : return Precedence.operand;
    }
}
//Changes infix to postfix notation then returns a string value.
public String postfix(String infix)
{
    String postfix = ""; 
    top = -1;
    stack = new Precedence[infix.length()];
    Precedence token;
    for(int i = 0; i<infix.length(); i++)
    {
        token = getToken(Character.toString(infix.charAt(i)));
        System.out.println("Token "+ infix.charAt(i) + " " + token);
        if(token == Precedence.operand)
        {
            postfix = postfix + infix.charAt(i);
        }
        else if(token == Precedence.rparen)
        {
            while(stack[top] != Precedence.lparen)
            {
                postfix = postfix + operators[pop().getIndex()];
            }
            pop();
        }
        else
        {
            while(top>=0 && isp[stack[top].getIndex()] >= icp[token.getIndex()])
            {
                postfix = postfix + operators[pop().getIndex()];
            }
            push(token);
        } System.out.println("Postfix '"+postfix+"' Stack "+Arrays.deepToString(stack));
    }
    while(top>=0 && (  (token = pop()) != Precedence.eos) )
    {
        postfix = postfix + operators[token.getIndex()];
    }
    return postfix;
}
}

我添加了一些调试打印语句来帮助查看发生了什么。

该代码不适用于两个字符运算符,例如 ->

还为堆栈使用 java.util.Deque

Deque<Precedence> stack = new ArrayDeque<Precedence>();

它为堆栈提供标准接口。

于 2016-01-27T17:33:38.417 回答