RPN评估器(分数,堆栈,队列)没有高级数据结构,初学者Java

时间:2014-03-06 04:10:00

标签: java object data-structures output

我有一个问题,为什么在世界上我的代码似乎在空间分裂,即使它应该到达“#”。我有一个问题似乎无法解决,当我尝试运行我的RPN评估程序时涉及输出的错误数据。我没有在类中共享的高级算法,这是一个赋值。非常基本,没有任何先进的要求。我被踩了。

示例输入:

  

(1/3)#< --------- // GOOD INPUT

     

(2/9)B(4/3)/#< ----------- //输入引起麻烦

基于输入的良好输出:

  

表达式1是:(1/3)

     

值为:(1/3)

     

中级结果:

基于第二个输入的错误输入:表达式2不应该像这样发生。它应该只是查找我输入的下一个RPN表达式。

  

表达式2是:(2/9)B

     

表达无效

     

中级结果:

     

表达式3是:/

     

表达无效

     

中级结果:

代码:我知道它很忙,但请耐心等待。我会发布所有内容,以便那些希望尝试自己运行它的人可以。 RPNEvaluator.java类是我正在努力解决的问题,我知道问题出在哪里。其余的都很好。

import java.util.Scanner;

public class RpnEvaluator
{
   private final int MAX_TOKEN = 100; 
   private Scanner stdin = new Scanner(System.in);
   private Queue myQueue = new Queue(MAX_TOKEN);
   private Stack myStack = new Stack(MAX_TOKEN);

   public void run() throws java.io.IOException
   {
      int count = 1;
      Fraction myInterMid;
      while(stdin.hasNext())
      {
         runOnce(count++);
         System.out.print("Intermediate results: ");
         while(!myQueue.isEmpty())
         {
            myInterMid = (Fraction)myQueue.remove();
            System.out.print(myInterMid.toString());
         }
         System.out.println();
         clear(myStack, myQueue);
      }
      System.out.println("Normal Termination of Program 3!");
   }

   private boolean isOperator(String input)
   {
      String[] oprtr = {"+", "-", "*"};
      for(String choice: oprtr)
         if(choice.equals(input))
            return true;
      return false;
   }

   private boolean isOperand(String input)
   {
      if(input.startsWith("(", 0) && input.contains("/") 
            && input.endsWith(")"))
         return true;
      return false;
   }

   private Fraction runOperation(String choice, Fraction op2, Fraction op1)
   {
      Fraction newFract = new Fraction();
      switch (choice)
      {
         case "*":
            newFract = new Fraction(op1.times(op2));
            break;
         case "+":
            newFract = new Fraction(op1.plus(op2));
            break;
         case "-":
            newFract = new Fraction(op1.minus(op2));
            break;
      }
      return newFract;
   }

   private void runOnce(int count)
   {
      String readIn = "";
      boolean valid = true;
      Fraction op1 = null;
      Fraction op2 = null;
      Fraction answer = null;
      Fraction myFract = null;

      doTypeCheck(readIn, myFract, valid, op1, op2, answer, count ); 
   }

   private void clear(Stack myStack, Queue myQueue)
   {
     myStack.clear();
     myQueue.clear();
   }

   private void runTheOperator(boolean valid, Fraction op2, Fraction op1,
         String readIn)
   {
       if(myStack.isEmpty())  
          valid = false;
       else
          op2 = (Fraction)myStack.pop();

       if(myStack.isEmpty())
          valid = false;
       else
       {
          op1 = (Fraction)myStack.pop();
          Fraction interMed = runOperation(readIn, op2, op1);
          myStack.push(interMed);
          myQueue.add(interMed);
       }
   }

   private void doTypeCheck(String readIn, Fraction myFract, boolean valid, 
         Fraction op1, Fraction op2, Fraction answer, int count)
   {
      Fraction stringFract;
      readIn = stdin.next();
      System.out.print("Expression " + count++ + " is: ");
      while(!readIn.equals("#") && valid == true)
      {
         if(isOperator(readIn))
            System.out.print(readIn);
         else if(isOperand(readIn))
         {
            stringFract = new Fraction(readIn);
            System.out.print(stringFract.toString());
         }
         else
            System.out.print(readIn);
         if(!isOperator(readIn) && isOperand(readIn))
         {
            myFract = new Fraction(readIn);
            myStack.push(myFract);
         }
         else if(isOperator(readIn))
            runTheOperator(valid, op2, op1, readIn);
         else
            valid = false;
         readIn = stdin.next();
      }
      System.out.println();
      if(myStack.isEmpty())
         valid = false;
      else
         answer = (Fraction)myStack.pop();

      if(!myStack.isEmpty())
         valid = false;

      checkMessageValid(valid, answer);
   }

   private void checkMessageValid(boolean valid, Fraction answer)
   {
      if(valid == false)
         System.out.println("Invalid Expression");
      else
         System.out.println("The value is: " + answer.toString());
   }
   }

所有其他代码:

STACK

/**
Keeps track of a Stack of Objects and allows for a user to create a stack,
check if the stack is empty or full, add an object to the top of the stack, 
and remove the object on top of the stack. Also allows user to clear out the
stack.
@author Adam Bloedel
*/
public class Stack
{
   private Object[] elements;
   private int top;

   /**
   Constructor to create a stack of Objects.
   @param size is the size of the stack.
   */
   public Stack(int size)
   {
      elements = new Object[size];
      top = 0;
   }

   /**
   Checks whether the stack is empty or if it is not empty.
   @return true if the top of the stack is equal to zero.
   */
   public boolean isEmpty()
   {
      return top == 0;
   }

   /**
   Checks whether the stack is full or if it is not full.
   @return true if the top of the stack is equal to the size of the stack
   */
   public boolean isFull()
   {
      return top == elements.length;
   }

   /**
   Pushes an Object onto the top of the stack.
   @param x is the Object that is pushed onto the top of the stack.
   */
   public void push(Object x)
   {
      elements[top++] = x;
   }

   /**
   Pops off the Object that is on the top of the stack.
   @return the Object which was popped off of the stack.
   */
   public Object pop()
   {
      return elements[--top];
   }

   public void clear()
   {
      for(int i = top; i > 0; i--)
         pop();
      top = 0;
   }
}

队列

/**
Keeps track of a Queue of Objects and allows for a user to create a queue,
check if the queue is empty or full, add an object to the queue to the rear,
and remove the object that is in the front of the queue. Also allows the user 
to clear out the queue.
@author Adam Bloedel
*/
public class Queue
{
   private Object [] elements;
   private int front, rear, count;

   /**
   Constructor for Queue that creates an array of objects of size size and 
   sets front, rear, and count to 0.
   @param size is the size of the queue. The max size.
   */
   public Queue(int size)
   {
      elements = new Object[size];
      front = 0;
      rear = 0;
      count = 0;
   }

   /**
   Checks if the Queue is empty or not. It is empty if count equals 0.
   @return true if the count is 0 and false if it does not return 0.
   */
   public boolean isEmpty()
   {
      return count == 0;
   }

   /**
   Checks if the Queue is full or not. It is full if the count is equal to the
   size of the array.
   @return true if the count equals the size of the array and false if it does
   not equal the size of the array.
   */
   public boolean isFull()
   {
      return count == elements.length;
   }

   /**
   Adds an object to the queue are the rear of the queue. Add then checks for
   the next spot that will be in the rear and increments the count.
   @param x is the object that gets added to the queue.
   */
   public void add(Object x)
   {
      elements[rear] = x;
      rear = (rear + 1) % elements.length;
      count++;
   }

   /**
   Removes an object from the queue that is in the front of the queue. It then
   rechecks what the front will be, decrements the count and returns the 
   object removed.
   @return x : the object that gets removed from the queue.
   */
   public Object remove()
   {
      Object x = elements[front];
      front = (front + 1) % elements.length;
      --count;
      return x;
   }

   /**
   Clears out the queue and resets the count, front, and rear all equal to 0
   like the constructor.
   */
   public void clear()
   {
      for(int i = 0; i < count; i++)
         remove();
      count = front = rear = 0;
   }
}

FRACTION

import java.util.StringTokenizer;

/**
Fraction class handles the individual creation of a Fraction by the 
Constructors listed. This class also handles the manipulation of individual
Fractions with the times, plus, and minus methods.
@author Adam Bloedel
*/
public class Fraction
{
   private int numerator, denominator;

   /**
   Default constructor that sets the numerator equal to one and the 
   denominator equal to 1 so that division by zero does not occur.
   */
   public Fraction()
   {
      numerator = 0;
      denominator = 1;
   }

   /**
   Copy constructor that copies the values of copyFract to the new object,
   Fraction.
   @param copyFract : The object(Fraction) that will be copied into the new
   object.
   */
   public Fraction(Fraction copyFract)
   {
      numerator = copyFract.numerator;
      denominator = copyFract.denominator;
   }

   /**
   Constructor that creates a Fraction object with specific numerator and 
   denominator numbers. If the denominator is 0, make the denominator 1. Else
   the fraction is created with the given numbers;
   @param num is the numerator for the new Fraction object
   @param denom is the denominator for the new Fraction object
   */
   public Fraction(int num, int denom)
   {
      if(denom == 0)
         denom = 1;
      else
      {
         numerator = num;
         denominator = denom;
         reduce();
      }
   }

   /**
   Another constructor that takes on a string and sorts through the string
   until the '/' is found and splits the two tokens to be the numerator and 
   denominator.
   @param fractString is the string of the fraction that will be parsed to be
   the Fraction stored
   */
   public Fraction(String fractString)
   {
      StringTokenizer str = new StringTokenizer(fractString, "(/)");
      numerator = Integer.parseInt(str.nextToken());
      denominator = Integer.parseInt(str.nextToken());
      reduce();
   }

   /**
   This method returns a string of the format: numerator/denominator as a 
   fraction would appear in Mathematics.
   @return the string that concatenates numerator/denominator together
   */
   @Override
   public String toString()
   {
      return "(" + numerator + "/" + denominator + ")";
   }

   /**
   This method checks for equality between a Fraction and an object that is 
   being checked in the parameter. If fract2 is an instance of Fraction,
   it checks if the numerator and denominator are equal to the numerator and 
   denominator of fract2.
   @param fract2 the object that is being checked for equality.
   @return true if fract2 is an instance of Fraction and if the numerator and
   denominator of the activated Fraction are equal to the numerator and
   denominator of fract2, which is being referred to by fract1.
   */
   public boolean equals(Object fract2)
   {
      if(fract2 instanceof Fraction)
      {
         Fraction fract1 = (Fraction)fract2;
         return numerator == fract1.numerator && 
                denominator == fract1.denominator;
      }
      return false;
   }

   /**
   Tests the Fraction that is multiplied or added together or even created
   via the constructors and reduces them to the most simplified form. Loops 
   through the lowest number to check if it is zero, if not then there is 
   more simplifying to do.
   */
   private void reduce()
   {
      int lowest, highest, temp;

      if(Math.abs(numerator) > Math.abs(denominator))
      {
         lowest = Math.abs(denominator);
         highest = Math.abs(numerator);
      }
      else
      {
         lowest = Math.abs(numerator);
         highest = Math.abs(denominator);
      }

      while(lowest != 0) // Loop to check if there is still more simplifying
      {
         temp = lowest;
         lowest = highest % lowest;
         highest = temp;
      }
      numerator /= highest;
      denominator /= highest;
      if(denominator < 0) // Makes denominator positive
      {
         numerator *= -1;
         denominator *= -1;
      }       }              /**       Adds two Fractions together and then reduces the resulting fraction. That       fraction is then returned as a new Fraction.       @param z is the second Fraction that is added onto the first Fraction.       @return newFract : this is the Fraction that is the resulting Fraction        from the addition of the first fraction with the fraction in the parameter.       */       public Fraction plus(Fraction z)       {          int myNumer = (numerator * z.denominator) + (z.numerator * denominator);          int myDenom = denominator * z.denominator;                    Fraction newFract = new Fraction("(" + myNumer + "/" + myDenom + ")");          newFract.reduce();                    return newFract;       }              /**       Subtracts the Fraction in the parameters from the first Fraction. The        resulting fraction is reduced if possible and then returned as a new        Fraction.       @param z is the second Fraction that is subtracted from the first fraction.       @return newFract  : this is the Fraction that is the resulting Fraction        from the subtraction of the second Fraction from the first Fraction.       */       public Fraction minus(Fraction z)       {          int myNumer = (numerator * z.denominator) -                (z.numerator * denominator);          int myDenom = denominator * z.denominator;                    Fraction newFract = new Fraction("(" + myNumer + "/" + myDenom + ")");          newFract.reduce();                    return newFract;       }              /**       Multiplies the first fraction and the fraction in the parameters together.
   The resulting Fraction is then reduced and returned as a new Fraction.
   @param z is the Fraction in the parameter that is multiplied by the first
   Fraction.
   @return newFract : this is the Fraction that is the resulting Fraction from
   the multiplication of the first Fraction and the second Fraction.
   */
   public Fraction times(Fraction z)
   {
      int myNumer = this.numerator * z.numerator;
      int myDenom = this.denominator * z.denominator;

      Fraction newFract = new Fraction("(" + myNumer + "/" + myDenom + ")");
      newFract.reduce();

      return newFract;
   }
}

MAIN PROG 3

/**
Runs the main for Program 3
@author Mr. Scanlan
*/
public class Prog3
{
   /**
   Runs RpnEvaluator.
   @param args  is unused
   */
   public static void main (String args[])
   {
      try
      {
         RpnEvaluator rpne = new RpnEvaluator();
         rpne.run();
      }
      catch (Exception e)
      {
         System.out.println("Program Error!");
      }
   }
}

1 个答案:

答案 0 :(得分:0)

在我看来,在达到'#'之前它不会继续,而是 直到达到'#'或者有效设置为false,这可能发生在 原因多少。一个是令牌既不被识别为 操作数或运算符。似乎确实存在'B'的东西。

您的doTypeCheck方法在许多重叠条件下非常混乱 并且输入和命名不明确(它确实比类型检查更多)。它 可能需要花一些时间来清理它。