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\$