1
 public void addItem() {
        System.out.println("Please type the item to add to the To-Do List");
        System.out.println();
        String newItem = inputread.next();
        toDoList.add(newItem);
        System.out.println("Your item has been added! Type any key and press Enter to continue");
        String discardMe = inputread.next();
        menu();
    }

This is my code, I'm just learning Java and trying to made a little "To-Do List" type program. As it stands, I can only add one word at a time. If, for example, I type "Pick Up Milk", the arrayList only stores "Pick".

I tried using inputread.nextLine() above, but then I get an "InputMismatchException". Any advice? I'm sure it's something simple.

Edited to include the whole class, per request:

public class ToDo {
    Scanner inputread = new Scanner(System.in);
    ArrayList<String> toDoList = new ArrayList<String>();


    public void menu() {
        clearConsole();
        System.out.println("Welcome to the To-Do program.");
        System.out.println();
        System.out.println();
        System.out.println("Please select an option from the following menu, using the number.:");
        System.out.println("1- View To-Do List");
        System.out.println("2- Add Item To List");
        System.out.println("3- Remove Item From List");
        int userinput = inputread.nextInt();

        switch (userinput) {
            case 1:
                clearConsole();
                displayList();
                System.out.println();
                System.out.println("This is your list. Type any key and press Enter to continue");
                String discardMe = inputread.next();
                menu();
                break;
            case 2:
                clearConsole();
                addItem();
                break;
            case 3:
                clearConsole();
                deleteItem();
                break;

        }
    }

    public void clearConsole() {
        for (int i = 0; i < 25; i++) {
            System.out.println();
        }
    }


    public void addItem() {
        System.out.println("Please type the item to add to the To-Do List");
        System.out.println();
        String newItem = inputread.nextLine();
        toDoList.add(newItem);
        System.out.println("Your item has been added! Type any key and press Enter to continue");
        String discardMe = inputread.next();
        menu();
    }

    public void displayList() {
        if (toDoList.isEmpty()) {
            System.out.println("For [REDACTED]'s sake, add an activity.");
        } else {
            for (String listItem: toDoList) {
                System.out.println(listItem);
            }
        }

    }

    public void deleteItem() {
        System.out.println("Please choose the number of the line you want to delete:");
        displayList();
        int userinput = inputread.nextInt();
        int listPos = userinput - 1;
        toDoList.remove(listPos);
        System.out.println("That item has been deleted. Type any key and press Enter to continue.");
        String discardMe = inputread.next();
        menu();
    }
}
Mad Vlad
  • 55
  • 5

4 Answers4

1

I would suggest using a BufferedReader instead of the Scanner class. The problem with a Scanner is that it looks for tokens between white spaces and new lines, so when you add something like Go to the store, each token between the white spaces will get picked up, and you will end up with go to the store, rather than 1 large token. You can get input using the BufferedReader by declaring it using:

public static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));

Then, in your addItem() method, in a while(true) loop, you read the input from the reader, then check if it is empty or not. IF it is empty, then you break the loop and exit the function, otherwise add an item to your list.

    System.out.println("Please type the item to add to the To-Do List"); // Output
    while (true) { // Continue adding items until user just hits enter
        String newItem = buf.readLine(); // read user input
        if (newItem == null || newItem.isEmpty()) { // check if the user entered anything, or just hit enter
            break; // If they didn't enter anything, then break the loop and drop out of the function
        }
        toDoList.add(newItem); // if they did enter something, add it to your to-do list

    }

For example, to test this I used a main method:

public static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));

public static void main(String[] args) throws IOException {
    List<String> toDoList = new ArrayList<String>();
    System.out.println("Please type the item to add to the To-Do List");
    while (true) {
        String newItem = buf.readLine();
        if (newItem == null || newItem.isEmpty()) {
            break;
        }
        toDoList.add(newItem);

    }
    System.out.println("Your item has been added! Type any key and press Enter to continue");

    for (String s : toDoList) {
        System.out.println(s);
    }
}

Then, when prompted for input I entered:

Please type the item to add to the To-Do List
Go to the grocery store and get milk
Stop by the gym and pay membership fees
Pick up flowers for the wife

And for output I got:

Your item has been added! Type any key and press Enter to continue
Go to the grocery store and get milk
Stop by the gym and pay membership fees
Pick up flowers for the wife
Mike Elofson
  • 2,017
  • 1
  • 10
  • 16
  • Thank you, I'm going to look more into BufferedReaders- Apparently I can't use it with .nextInt? I'll have to read more about how to use it, thank you. It does seem to be a better option. – Mad Vlad Jan 21 '15 at 19:00
  • @MadVlad Sounds good! Feel free to reach out if you have any questions, I am more than happy to help. You can do data type checks after the value is read in should you need to check. Feel free to mark my answer as the answer to your question if it is sufficient! Thanks :) – Mike Elofson Jan 21 '15 at 19:02
1

You have several problems in this code.

Let's first address your input issues.

In the menu, you read a number. When you use scanner.next(), scanner.nextInt() etc., it reads the following item up to - but not including - any white space or newline. So the white space or newline remain in the buffer waiting to be read.

Now, when you go to the addItem() and use nextLine(), it reads just that whitespace or newline. If it was just a newline (a Return you pressed), then you get an empty string, and you probably don't want to add that to the list. If you use next() it will skip that newline but... it will read just one word.

So you need to have a nextLine() after your nextInt() in the menu. After you read your integer, you'll clear the buffer up to and including the newline.

Then, inside the addItem() method, you'll be able to use nextLine() again, because it will now start on a fresh new line - and it will read the next line in its entirety.

Also, the discardMe part has to be with nextLine(), not with next(), otherwise it will not clear the end-of-line for the next operation.


Your other problem is something you didn't ask about. What you currently do is basically go into the menu, then go into an operation, then go into the menu, then an operation. You keep calling more and more functions, and you never return, or rather, you return from all when you display the list.

In time, this may cause a stack overflow.

The proper way to do this is not to call menu() from inside the operational methods, but rather, to have a loop in the menu() method, which shows the menu, calls the appropriate operational method, and when it returns (clears its space on the stack), loops back to the menu and so on. This keeps your stack nice and flat.

And of course, you should have a "Quit" option on your menu.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • Thank you for your high-level structural comments- I'll be sure to keep this in mind in the future as I understand more about what I'm doing. – Mad Vlad Jan 21 '15 at 19:02
0

an example for Stultuskes idea:

    public void addItem() {
        System.out.println("Please type the item to add to the To-Do List");
        System.out.println();
        try (Scanner in = new Scanner(System.in)) {
            while (in.hasNext()) {
                String newItem = in.next();
                toDoList.add(newItem);
                System.out
                    .println("Your item has been added! Type any key and press Enter to continue");
            }
        }
        System.out.println(toDoList);
}
Steffen
  • 341
  • 1
  • 12
  • okay, a litte misunderstanding. You want to add ALL words? Then the other solution using `nextLine()` is better. – Steffen Jan 21 '15 at 14:44
  • Yeah, what I'm trying to do is allow the user to type something like "Go to the Grocery store and grab milk" and have it store as one entry. Tom, above, posted something that seems like it may be part of the problem, I haven't had a chance to look yet. – Mad Vlad Jan 21 '15 at 14:51
0
public void addItem() {
    System.out.println("Please type the item to add to the To-Do List");
    //The skip gets over the leftover newline character
    inputread.skip("\n");
    String newItem = inputread.nextLine();
    toDoList.add(newItem);
    System.out.println("Your item has been added! Type any key and press Enter to continue");
    String discardMe = inputread.next();
    menu();
}

Putting in the skip fixed it for me. I want to thank you guys for your answers.

Mad Vlad
  • 55
  • 5