Adan Vivero
Adan Vivero

Reputation: 422

How to receive a previous line of text from an Stack in Java

I am currently struggling with a code. The problem mainly occurs with the array and trying to reach back.

This file only requires a main method that does the following until the user enters "quit":

• Prompts the user for a URL to visit, to go back (only when possible), or to quit

• Visits and displays an entered URL

• Goes back to and displays the previously visited URL (if possible)

• If the user enters "back" when there isn't a page to go back to, an appropriate message should be displayed.

Here's an example of an output:

Enter a URL or "quit": back

No URL to go back to

Enter a URL or "quit": http://www.wwe.com

Current URL: http://www.wwe.com

Enter a URL or "quit": back

No URL to go back to

Current URL: http://www.wwe.com

Enter a URL or "quit": http://www.amazon.com

Current URL: http://www.amazon.com

Enter a URL, "back", or "quit": http://www.google.com

Current URL: http://www.google.com

Enter a URL, "back", or "quit": back

Current URL: http://www.amazon.com

Enter a URL, "back", or "quit": back

Current URL: http://www.wwe.com

Enter a URL or "quit": quit

Here's my current code:

public class BrowsingHistory
{
 public static void main(String [] args)
 {

    Scanner url = new Scanner(System.in);
    String web = "";
    String currentURL = "";
    Stack<String> myStack = new Stack<>();
    System.out.print("Enter a URL or \"quit\": ");
    web = url.nextLine();
    while (!web.contains("quit"))
    {
        System.out.println();
        System.out.print("Enter a URL, \"back\", or \"quit\": ");
        web = url.nextLine();
        if(web.equals("back") && myStack.isEmpty())
        {
            System.out.println("No URL to go back to");

        }
            else if(!web.equals("back"))
            {
                myStack.push(web);
                System.out.println("Current URL: " + myStack.peek());
            }
            else
                {
                    System.out.println("No URL to go back to");
                    System.out.println("Current URL: " + myStack.pop());
        }
        }
}
}

Here are the tests it needs to pass, just so it's clarified:

 @Test
 void testMain()
 {
     setInput("back\nhttp://www.uwec.edu\nback\nhttp://www.amazon.com\nhttp://.    w.google.com\nback\nback\nquit\n");

BrowsingHistory.main(null);

 String mainOutput = outContent.toString();

  Scanner driverOut = new Scanner(mainOutput);

     String outputLine = getNextOutputLine(driverOut);

    assertEquals("Enter a URL or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (initial prompt problem)");

Error happens in this line below:

    assertEquals("No URL to go back to", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (can't go back issue)");

the rest of this passes:

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("Current URL: http://www.uwec.edu", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("No URL to go back to", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (can't go back issue)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Current URL: http://www.uwec.edu", outputLine.trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("Current URL: http://www.amazon.com", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL, \"back\", or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("Current URL: http://www.google.com", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL, \"back\", or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("Current URL: http://www.amazon.com", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL, \"back\", or \"quit\":", outputLine.substring(0, outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (prompt problem)");
    assertEquals("Current URL: http://www.uwec.edu", outputLine.substring(outputLine.indexOf(":")+1).trim(), "BrowsingHistory doesn't run as expected (current url problem)");

    outputLine = getNextOutputLine(driverOut);
    assertEquals("Enter a URL or \"quit\":", outputLine.trim(), "BrowsingHistory doesn't run as expected (prompt problem)");

    assertFalse(driverOut.hasNext(), "BrowsingHistory doesn't run as expected (quit problem)");

    driverOut.close();
}

Upvotes: 0

Views: 171

Answers (3)

Ridcully
Ridcully

Reputation: 23665

Using Stack class instead of an ArrayList would make your life much easier.

Use push() to add new urls to stack.

Use empty() to check if you can go back.

Use pop() to go back.

EDIT - supporting forward

If you want to support a 'forward' comand as well, you can use a second stack and push the urls you popped from the history stack on that forward-stack. When the 'forward' command is entered, check, if the forward-stack is empty, and if not, pop the url from there and push it back onto the history-stack.

EDIT 2 - example code

Here is some rudimentry code to explain the 2 stacks solution:

Stack<String> historyStack = new Stack<>();
Stack<String> forwardStack = new Stack<>();
String currentUrl = null;

boolean running = true;
while(running) {
    String input = getUserInput();
    switch(input) {
        case "quit":
            running = false;
            break;
        case "back":               
            if (!historyStack.empty()) {
                if (currentUrl != null) {
                    forwardUrl.push(currentUrl);
                }
                currentUrl = historyStack.pop();
                System.out.println(currentUrl);
            } else {
                System.out.println("nothing to go back to");
            }
            break;
        case "forward":
            if (!forwardStack.empty()) {
                if (currentUrl != null) {
                    historyStack.push(currentUrl);
                }
                currentUrl = forwardStack.pop();
                System.out.println(url);
            } else {
                System.out.println("nothing to go forward to");
            }
            break;
        default:
            if (currentUrl != null) {
                historyStack.push(currentUrl);
            }
            currentUrl = input;
            System.out.println(url);
            // entering a new url makes forward stack invalid
            forwardStack.clear();
    }
}

Upvotes: 2

Nicholas K
Nicholas K

Reputation: 15433

You can change your logic to as follows :

ArrayList<String> webs = new ArrayList<String>();
String web = "";
Scanner url = new Scanner(System.in);

int count = 0;
while (!web.contains("quit")) {
    System.out.println("Enter a URL or \"quit\":");
    web = url.next();
    if (!web.equals("back")) {
        webs.add(web);
        count = webs.size();
    } else if (web.equals("back") && !webs.isEmpty()) {
        if (count > 0) {
            count--;
            System.out.println(webs.get(count));
        } else {
            System.out.println("No url to go back to");
        }
    }
}

Note the following points :

  1. We add only Strings that are not equal to back
  2. In your previous implementation the first url entered was not getting inserted into your list.
  3. After an element is added to the list, count is reset to the size of the list.

As others have pointed out, the same can be achieved much more easily by using a Stack

Scanner url = new Scanner(System.in);
String web = "";
Stack<String> myStack = new Stack<>();
while (!web.contains("quit")) {
    System.out.println("Enter a URL or \"quit\":");
    web = url.next();
    if (!web.equals("back") && !web.equals("quit")) {
        myStack.push(web);
    } else {
        if (!myStack.isEmpty()) {
            System.out.println(myStack.pop());
        } else {
            System.out.println("No url to go back to");
        }
    }
}

Upvotes: 1

Oleg Cherednik
Oleg Cherednik

Reputation: 18255

You use incorrect data structure. List is OK, but using Stack is more correct here: you add to the end and retrieve from the end, this id LIFO.

private static final String QUIT = "quit";
private static final String BACK = "back";

try (Scanner url = new Scanner(System.in)) {
    Deque<String> stack = new LinkedList<>();

    while (true) {
        System.out.print("Enter a URL, \"" + BACK + "\" or \"" + QUIT + "\": ");
        String str = url.next();

        if (str.equalsIgnoreCase(QUIT))
            break;
        else if (str.equalsIgnoreCase(BACK)) {
            if (!stack.isEmpty())
                stack.pop();
            System.out.println(stack.isEmpty() ? "No URL to go back to" : stack.element());
        } else
            stack.push(str);
    }
}

Demo

Enter a URL, "back" or "QUIT": http://www.wwe.com
Enter a URL, "back" or "QUIT": http://www.amazon.com
Enter a URL, "back" or "QUIT": http://www.google.com
Enter a URL, "back" or "QUIT": back
http://www.amazon.com
Enter a URL, "back" or "QUIT": back
http://www.wwe.com
Enter a URL, "back" or "QUIT": back
No URL to go back to
Enter a URL, "back" or "QUIT": quit

Upvotes: 0

Related Questions