1. /**
  2.  * @author David Richardson <richardson-d@iam.uwinnipeg.ca>
  3.  * @version 2011.0203
  4.  * @since 1.6
  5.  */
  6. public class Problem2
  7. {
  8. /**
  9. * main() is a driver method for the Expression class.
  10. *
  11. * This method goes through the creation, and displaying of
  12. * Expression objects in postfix and infix forms
  13. */
  14. public static void main (String [] args)
  15. {
  16. System.out.println("ACS2947: Assignment 1 by David Richardson");
  17. long startTime = System.currentTimeMillis();
  18.  
  19. /**
  20. * When creating an Expression object, you could also use a single
  21. * object and change the expression with *.getInfix(str) and then
  22. * update the postfix expression with *.convertToPostfix()
  23. */
  24. Expression [] expr = {
  25. new Expression ("A+B-C"),
  26. new Expression ("(A+B)*C"),
  27. new Expression ("(A+B)*(C-D)"),
  28. new Expression ("A+((B+C)*(E-F)-G)/(H-I)"),
  29. new Expression ("A+B*(C+D)-E/F*G+H")
  30. };
  31.  
  32. for(int i = 0; i < expr.length; i++)
  33. {
  34. System.out.println("\nInfix Expression: \t" + expr[i].showInfix());
  35. System.out.println("Postfix Expression: \t" + expr[i].showPostfix());
  36. }
  37.  
  38. long elapsedTime = System.currentTimeMillis() - startTime;
  39. System.out.println("\nProgram Finished in " + elapsedTime + "ms. ");
  40. }//end main()
  41. }//end class Problem2
  42.  
  43. /**
  44.  * @author David Richardson <richardson-d@iam.uwinnipeg.ca>
  45.  * @version 2011.0203
  46.  * @since 1.6
  47.  */
  48. import java.util.Stack;
  49.  
  50.  
  51. public class Expression
  52. {
  53. private String infix = ""; //The infix form of the expression
  54. private String postfix = ""; //The postfix form of the expression
  55.  
  56. /**
  57. * Constructors
  58. * Expression() - An empty constructor, this will create an object without
  59. * storing anything in the infix/postfix values. These values will
  60. * need to be set later with .getInfix() and .convertToPostfix().
  61. *
  62. * Expression(String) - This constructor receives a expression in infix
  63. * format and then calls the convertToPostfix method, this storing
  64. * values in both infix and postfix variables.
  65. *
  66. * @param String str - An infix expression passed as a string
  67. */
  68. public Expression()
  69. {
  70. //empty
  71. }
  72.  
  73. public Expression(String str)
  74. {
  75. getInfix(str);
  76. }
  77.  
  78. /**
  79. * getInfix(String) - Method stores a value in the infix variable, and
  80. * calls the convertToPostfix() method.
  81. *
  82. * @param String infix - An infix expression passed as a string.
  83. */
  84. public void getInfix(String infix)
  85. {
  86. this.infix = infix;
  87. convertToPostfix(); //Could be commented out
  88. }
  89.  
  90. /**
  91. * showInfix() - An accessor method to return the contents of the infix
  92. * string.
  93. */
  94. public String showInfix()
  95. {
  96. return infix.toString();
  97. }
  98.  
  99. /**
  100. * showPostfix() - An accessor method to return the contents of the
  101. * postfix string.
  102. */
  103. public String showPostfix()
  104. {
  105. return postfix.toString();
  106. }
  107.  
  108. /**
  109. * convertToPostfix() - Converts an expression from infix to postfix
  110. *
  111. * Uses a stack based algorithm to change the infix expression to
  112. * it's postfix equivilant.
  113. */
  114. protected void convertToPostfix()
  115. {
  116. final String operators = "+-*/"; //Valid Operations
  117. Stack<Character> pfx = new Stack<Character> (); //Temp. Stack Storage
  118. String postfix = ""; //Temp. Postfix Expr.
  119.  
  120. /**
  121. * The following for loop will cycle through every symbol in the infix
  122. * expression, and based on the current symbol it will create a postfix
  123. * expression.
  124. */
  125. for(int i = 0; i < infix.length(); i++)
  126. {
  127. char sym = infix.charAt(i); //Current Symbol being read.
  128.  
  129. /**
  130. * If sym is an operand (a value) as opposed to an operator
  131. */
  132. if(operators.indexOf(sym) < 0)
  133. {
  134. if( sym == '(' )
  135. {
  136. pfx.push(sym);
  137. }//end if
  138.  
  139. /**
  140. * This marks the end of an sub statement, it will pop
  141. * off all symbols stored up until a "(" (start of sub
  142. * statement) and then append them to the postfix string
  143. */
  144. else if( sym == ')' )
  145. {
  146. while( pfx.peek() != '(' )
  147. {
  148. postfix += pfx.pop();
  149. }
  150.  
  151. pfx.pop();
  152. }//end else-if
  153.  
  154. else
  155. {
  156. postfix += sym;
  157. }//end else
  158. }//end if
  159.  
  160. /**
  161. * If sym is an operator (listed above in "operators")
  162. */
  163. if(operators.indexOf(sym) >= 0) //sym is an operator
  164. {
  165. /**
  166. * The following code gets placed in a try catch statement
  167. * because wheen using .peek() it's possible to throw an
  168. * EmptyStackException, which if not caught, will crash.
  169. */
  170. try
  171. {
  172. /**
  173. * The while loop cycles through all operators in the
  174. * stack back to the last opening parenthesis or until
  175. * the stack is empty, whichever comes first. It places
  176. * the value on the top of the stack in the postfix string
  177. * by popping it off the stack.
  178. */
  179. while( pfx.peek() != '(' && !pfx.empty() )
  180. {
  181. if(precedence(pfx.peek(), sym))
  182. {
  183. postfix += pfx.pop();
  184. }//end if
  185.  
  186. /**
  187. * The else statement here is executed so that the
  188. * objects in the stack do not take precedence, this
  189. * prevents an infinite loop.
  190. */
  191. else
  192. {
  193. break;
  194. }//end else
  195. }//end while
  196. }//end try
  197.  
  198. /**
  199. * This catch statement should never be executed, but if the
  200. * program is crashing then you can uncomment the println to
  201. * debug any errors you may be having.
  202. */
  203. catch ( Exception e)
  204. {
  205. //System.out.println(e);
  206. }//end catch
  207.  
  208. pfx.push(sym); //Pushes the current sym onto the stack.
  209. }//end if
  210. }//end for
  211.  
  212. /**
  213. * The following while statement gets executed after all symbols
  214. * from the infix expression have been loaded and sorted. It clears
  215. * out any remaining characters (operators) from the stack, and
  216. * appends them to the end of the postfix expression.
  217. */
  218. while( !pfx.empty() )
  219. {
  220. postfix += pfx.pop();
  221. }//end while
  222.  
  223. this.postfix = postfix; //Stores the postfix expr in the class var
  224. }//end convertToPostfix()
  225.  
  226. /**
  227. * precedence(char, char) - returns true if the precendence of the first
  228. * operator is greater than the precedence of the second operator.
  229. *
  230. * @param operA - char representation of a binary operator.
  231. * operB - char representation of another binary operator.
  232. *
  233. * @return true: If operA precendence > operB.
  234. * false: otherwise.
  235. */
  236. private static boolean precedence(char operA, char operB)
  237. {
  238. boolean isGreater = true;
  239.  
  240. if(operB == '*' || operB == '/' && operA == '+' || operA == '-')
  241. {
  242. isGreater = false;
  243. }//end if
  244.  
  245. return isGreater;
  246. }//end precedence(char, char)
  247. }//end Expression class