Skip to main content
2 of 3
Change so that Numbers.txt is visible separately

Implementation of stack

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 so I have to use "System.lineSeparator()" and I don't understend why is that?
  • 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?