Java计算器版本4

时间:2012-11-26 23:20:16

标签: java calculator rpn shunting-yard

计算器现在几乎正常工作。它现在为它读入的每个方程给出了相同的答案?

输出结束为:     49 + 62 * 61-36     15.666666666666668     4/64     15.666666666666668     (53 + 26)     15.666666666666668     0 * 72     15.666666666666668     21-85 + 75-85     15.666666666666668     90 * 76-50 + 67     15.666666666666668     46 * 89-15     15.666666666666668     34 / 83-38     15.666666666666668     七十六分之二十○/ 14 + 92-15     15.666666666666668     5 * 10 / 3-1     15.666666666666668

而不是每个等式都有答案吗?

我的方法中是否遗漏了一些东西?

由于

所有代码如下所示。任何帮助将不胜感激。

Stack class:

 import java.util.Iterator;
 import java.util.NoSuchElementException;

public class myStack<Item> implements Iterable<Item> {
private int N; // size of the stack
private Node first; // top of stack

private class Node {
    private Item item;
    private Node next;
}

/**
 * Create an empty stack.
 */
public myStack() {
    first = null;
    N = 0;
    assert check();
}

public boolean isEmpty() {
    return first == null;
}

public int size() {
    return N;
}

public void push(Item item) {
    Node oldfirst = first;
    first = new Node();
    first.item = item;
    first.next = oldfirst;
    N++;
    assert check();
}

public Item pop() {
    if (isEmpty())
        throw new NoSuchElementException("Stack underflow");
    Item item = first.item; // save item to return
    first = first.next; // delete first node
    N--;
    assert check();
    return item; // return the saved item
}

public Item peek() {
    if (isEmpty())
        throw new NoSuchElementException("Stack underflow");
    return first.item;
}

public String toString() {
    StringBuilder s = new StringBuilder();
    for (Item item : this)
        s.append(item + " ");
    return s.toString();
}

// check internal invariants
private boolean check() {
    if (N == 0) {
        if (first != null)
            return false;
    } else if (N == 1) {
        if (first == null)
            return false;
        if (first.next != null)
            return false;
    } else {
        if (first.next == null)
            return false;
    }

    // check internal consistency of instance variable N
    int numberOfNodes = 0;
    for (Node x = first; x != null; x = x.next) {
        numberOfNodes++;
    }
    if (numberOfNodes != N)
        return false;

    return true;
}

public Object[] toArray(String[] elementData) {
    return (Object[]) elementData.clone();
}

public Iterator<Item> iterator() {
    return new ListIterator();
}

// did not implement remove as it was not needed
private class ListIterator implements Iterator<Item> {
    private Node current = first;

    public boolean hasNext() {
        return current != null;
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }

    public Item next() {
        if (!hasNext())
            throw new NoSuchElementException();
        Item item = current.item;
        current = current.next;
        return item;
    }
}
}

数组列表类

import java.util.Arrays;

public class myArrayList<Item>{

private Object[] myStore;
private int actSize = 0;

public myArrayList() {
    myStore = new Object[100];
}

public Object get(int index) {
    if (index < actSize) {
        return myStore[index];
    } else {
        throw new ArrayIndexOutOfBoundsException();
    }
}
public void add(Object obj) {
    if (myStore.length - actSize <= 0) {
        increaseListSize();
    }
    myStore[actSize++] = obj;
}

public Object remove(int index) {
    if (index < actSize) {
        Object obj = myStore[index];
        myStore[index] = null;
        int tmp = index;
        while (tmp < actSize) {
            myStore[tmp] = myStore[tmp + 1];
            myStore[tmp + 1] = null;
            tmp++;
        }
        actSize--;
        return obj;
    } else {
        throw new ArrayIndexOutOfBoundsException();
    }

}

public int size() {
    return actSize;
}

private void increaseListSize() {
    myStore = Arrays.copyOf(myStore, myStore.length * 2);
}

@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size())
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(myStore, size(), a.getClass());
    System.arraycopy(myStore, 0, a, 0, size());
    if (a.length > size())
        a[size()] = null;
    return a;
}


}

用于等式处理的TestClass

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 import java.util.StringTokenizer;

public class TestClass {

private static final int LEFT_ASSOC = 0;
private static final int RIGHT_ASSOC = 1;
static String OPERATORS1 = "+-*/()";

// Operators
private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();
static {
    // Map<"token", []{precedence, associativity}>
    OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });
    OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });
    OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });
    OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });
    OPERATORS.put("(", new int[] {1, LEFT_ASSOC});
    OPERATORS.put(")", new int[] {1, LEFT_ASSOC});
}

private static boolean isOperator(String token) {
    return OPERATORS.containsKey(token);
}

// Test associativity of operator token
private static boolean isAssociative(String token, int type) {
    if (!isOperator(token)) {
        throw new IllegalArgumentException("Invalid token: " + token);
    }

    if (OPERATORS.get(token)[1] == type) {
        return true;
    }
    return false;
}

// Compare precedence of operators.
private static final int cmpPrecedence(String token1, String token2) {
    if (!isOperator(token1) || !isOperator(token2)) {
        throw new IllegalArgumentException("Invalid tokens: " + token1
                + " " + token2);
    }
    return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];
}

public static String[] infixToRPN(String[] inputTokens) {
    myArrayList<String> out = new myArrayList<String>();
    myStack<String> stack = new myStack<String>();
    // For each token
    for (String token : inputTokens) {
        StringTokenizer tokens = new StringTokenizer(token,OPERATORS1,true);
        while (tokens.hasMoreTokens()) {
            token = tokens.nextToken();


            // If token is an operator
            if (isOperator(token)) {
                // While stack not empty AND stack top element
                // is an operator
                while (!stack.isEmpty() && isOperator(stack.peek())) {
                    if ((isAssociative(token, LEFT_ASSOC) && cmpPrecedence(
                            token, stack.peek()) <= 0)
                            || (isAssociative(token, RIGHT_ASSOC) && cmpPrecedence(
                                    token, stack.peek()) < 0)) {
                        out.add(stack.pop());
                        continue;
                    }
                    break;
                }
                // Push the new operator on the stack
                stack.push(token);
            }
            // If token is a left bracket '('
            else if (token.equals("(")) {
                stack.push(token); 
            }
            // If token is a right bracket ')'
            else if (token.equals(")")) {
                while (!stack.isEmpty() && !stack.peek().equals("(")) {
                    out.add(stack.pop());
                }
                stack.pop();
            }
            // If token is a number
            else {
                out.add(token);
            }
        }
        while (!stack.isEmpty()) {
            out.add(stack.pop());
        }
    }
    String[] output = new String[out.size()];
    return out.toArray(output);
}

public static double RPNtoDouble(String[] tokens) {
    myStack<String> stack = new myStack<String>();

    // For each token

    for (String token : tokens) {
        //System.out.println( "Working this token: " + token );
        // If the token is a value push it onto the stack
        if (!isOperator(token)) {
            stack.push(token);
        } else {
            // Token is an operator: pop top two entries
            Double d2 = Double.valueOf(stack.pop());
            Double d1 = Double.valueOf(stack.pop());

            // Get the result
            Double result = token.compareTo("+") == 0 ? d1 + d2 : token
                    .compareTo("-") == 0 ? d1 - d2
                            : token.compareTo("*") == 0 ? d1 * d2 : d1 / d2;

            // Push result onto stack
            stack.push(String.valueOf(result));
        }
    }

    return Double.valueOf(stack.pop());
}

static public void main(String[] args) throws IOException {
    File file = new File("testEquations.txt");
    String[] lines = new String[1];

    try {
        FileReader reader = new FileReader(file);
        @SuppressWarnings("resource")
        BufferedReader buffReader = new BufferedReader(reader);
        int x = 0;
        String s;
        while ((s = buffReader.readLine()) != null) {
            lines[x] = s;
            x++;
        }
    } catch (IOException e) {
        System.exit(0);
    }
    // test printing string array
    for (String s : lines) {
        System.out.println("" + s);
        String[] output =infixToRPN(lines);
        System.out.println(RPNtoDouble(output));

    }


}

}

1 个答案:

答案 0 :(得分:3)

你的问题在这里:

String[] lines = new String[1];

    try {
        FileReader reader = new FileReader(file);
        @SuppressWarnings("resource")
        BufferedReader buffReader = new BufferedReader(reader);
        int x = 0;
        String s;
        while ((s = buffReader.readLine()) != null) {
            lines[x] = s;
            x++;
        }
        ...

你定义了一个size = 1的字符串数组,但是如果x超出了这个数组的边界,你就不会在循环内部进行检查。

这样想一下:

int Size = // define the size..;
String[] lines = new String[Size];
...
while (x < Size && (s = buffReader.readLine()) != null)) {
            lines[x] = s;
            x++;
        }

当你的x比较大,那么x < Size将评估为false,从而退出循环。

关于您遇到的一个错误 ArrayIndexOutOfBoundsException

  

抛出表示已使用非法访问数组   指数。该指数为负数或大于或等于   数组的大小。 (source

另一个错误 NoSuchElementException

  

由Enumeration的nextElement方法抛出以指示   枚举中没有更多元素(source)。

另一个问题是:

// test printing string array
    for (String s : lines)
    {
        System.out.println("" + s);
        String[] output =infixToRPN(lines);
        System.out.println(RPNtoDouble(output));

    }

您必须将s而不是lines传递给方法infixToRPN,这就是为什么您获得相同的输出,因为您提供相同的输入。

请记住,infixToRPN收到的String []不是像's'这样的字符串,但我留给您找一个解决方法。