Task:
Create a class RPNStack which represents a stack of objects of type Node. Class RPNStack contains only one private field top of type Node. Objects of type Node represent data that are pushed on the stack: each object contains in its field val a double and in field next a reference to the next node (as in a singly-linked list - top plays here the role of the head ). Class RPNStack offers three methods:
- method public void push(double d) pushing new object of type Node on top of the stack (i.e., it becomes the new top);
- method public double pop() removing the top node (so the next node becomes the new top) and returning val from the removed node;
- method public boolean empty() returning true if and only if the stack is empty (top is null); otherwise false is returned.
Note that stack is a singly-linked list where adding and removing elements is always performed at the beginning.
The main program reads a le with data representing arithmetic expressions in the Reverse Polish Notation (RPN), for example:
2 7 5 + * 20 - 1 4 / /
After reading each line, it is split (using spaces as separators) and for each token:
- if it is string "+", we pop two numbers from the stack, add them and push the result on the stack;
- if it is string "*", we do the same but myltiplying the numbers instead of adding them;
- if it is string "-", we pop two elements, subtract the one popped as the first from the one popped as the second and push the result on the stack;
- if it is string "/", we do the same but dividing the numbers instead of subtracting them;
- if it is not "+", "*", "-" or "/", we interpret it as a number of type double and we push it onto the stack.
After all tokens from the line have been processed, we pop the remaining number o the stack, which should be the value of the whole expression. We then print the line and the result. We also check if the stack is now empty; if not, we inform the user about this fact, we clear the stack and repeat the procedure for the remaining lines of the input file.
My Implementation:
I sligtly modify program to write to the file just to practice
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { String fileName = "Numbers.txt"; String fileRes = "NumbersCalc.txt"; Path filein = Paths.get(fileName); if (!Files.exists(filein) || !Files.isReadable(filein) || Files.isDirectory(filein)) { System.out.println("Invalid input file !!!"); System.exit(1); } try (BufferedWriter bw = Files.newBufferedWriter(Paths.get(fileRes)); BufferedReader br = Files.newBufferedReader(filein) ) { String line; while ( (line = br.readLine()) != null) { String[] lineParts = line.split("\\s+"); for (String string : lineParts) { if(string.equals("+")){ RPNStack.push( RPNStack.pop() + RPNStack.pop() ); }else if(string.equals("-")){ RPNStack.push( RPNStack.pop() - RPNStack.pop() ); }else if(string.equals("*")){ RPNStack.push( RPNStack.pop() * RPNStack.pop() ); }else if(string.equals("/")){ RPNStack.push( RPNStack.pop() / RPNStack.pop() ); }else if(!string.equals("+") &&!string.equals("-")&&!string.equals("*")&&!string.equals("/")){ RPNStack.push(Double.parseDouble(string)); } } bw.write(RPNStack.pop()+System.lineSeparator()/*"\n"*/); } System.out.println("Results written to " + fileRes); if(RPNStack.empty()) System.out.println("Stack is empty"); } catch(IOException e) { System.out.println("Something wrong"); System.exit(1); } } } public class RPNStack { private static Node top = null; public static Node getTop() { return top; } public static void push(double d){ if(top == null) top = new Node(d); else top = new Node(d, top); } public static double pop(){ double buf = top.getVal(); top = top.getNext(); return buf; } public static boolean empty(){ if(top == null) return true; else return false; } } public class Node { private double val; private Node next; public double getVal() { return val; } public Node getNext() { return next; } public Node(double val, Node next){ this.val=val; this.next=next; } public Node(double val){ this(val,null); } }
Numbers.txt:
2 7 5 + * 20 - 1 4 / / 2 7 5 + * 20 - 1 4 / /
Questions:
- I assume that we need to use static function in class RPNStack. Is it right?
- When I use BuffedWriter "\n" simply doesn't work(I expect print values from new line but its go one by one) so I have to use "System.lineSeparator()" and I don't understend why is that? Runing on Win 8.1\Eclipce Mars
- Is there a better way to recognise symbols than bunch on if else statements?
- Is it okay to use in try\catch only IOException? Or we need to use one more catch for Exception?
- What else can be done better?
\r\n
constitutes a newline, which is whatSystem.lineSeparator()
will return in that OS. It's recommended to use that for cross-platform compatibility.\$\endgroup\$