Search code examples
javainputwhile-looplogicpalindrome

.hasNext() and .next() cause infinite while loop


I'm in a beginner level coding class and this is my assignment: Write a void method called palindromeCheck that takes NO argument. The method should have functionality to check whether or not the word(s) is(are) a palindrome and print to the screen all of the palindromes, one per line. Also, the last line of the output should have the message: “There are x palindromes out of y words provided by user” (where x is the number of palindrome words detected, and y is the total number of words entered by user). Hint: for this lab exercise you will need the following methods on String objects: length() gives the length of a string (that is, the number of characters it contains) and charAt(i) - gives the character at position i. Since the input entered is supposed to be separated by white space I'm confused on how to create the while loop that iterates per word entered. My professor gave us help in the form of a skeleton for the method she wants us to create. In that skeleton is a while loop that performs actions for each word entered

while (keyboard.hasNext()){
someWord = keyboard.next();
// some code that performs actions
}

This while loop works but after it's done and supposed to terminate it just prompts to enter more input. Here is my current code below, which should be finished aside from this logical error.

public static void palindromeCheck(){
    String someWord = ""; // Stores words read from user input
    int count = 0;        // keeps track of Palindrome words only
    int total = 0; // Counts the total number of lines read from the given text file
    int score = 0; // used as a condition to count palindrome words   
    System.out.println("Enter some words separated by white space."); 
    Scanner keyboard = new Scanner(System.in);

    while (keyboard.hasNext()) { // for each word user enters
        someWord = keyboard.next(); // store each word in a string variable and then do operations
        score = 0;
        int n = (someWord.length()-1);
        for (int i = 0; i < (someWord.length()-2); i++){
            for (int j = (someWord.length()-1); i < (someWord.length()-2); j--){
                j = n;
                n--;
                if(someWord.charAt(i) == someWord.charAt(j)){
                    break;
                }
                else
                    score++;
            }
        }
        if(score == 0){ // if word is palindrome adds to counter
            count++;
        }
        total++; // increment number of words as you read each one
        //System.out.println("  " + total + " " + someWord);   // test
    }
    System.out.println("There are " + count + " palindromes out of " + total + " words provided by user.");
}

Solution

  • You can't depend on keyboard.hasNext() to tell you when your program should stop. A keyboard is basically an infinite source of input, so keyboard.hasNext() might never return false. If there is some data from the previous input line that hasn't been processed yet, it will return true immediately. But if all the data from the previous line was used up, keyboard.hasNext() will just sit and wait for you to type another line, and then return true once you've hit ENTER.

    Since you can't depend on keyboard.hasNext() to tell you that it's time to stop processing words, you have to program some other way to decide when the program should stop.

    The nicest way, from your user's point of view, is to read one entire line of input, process all the words on that line, and then stop. You use keyboard.nextLine() to read a whole line of input:

    String inputLine = keyboard.nextLine();
    

    After that, you have any number of choices as to how to break that line up into individual words. Here are examples of two ways.

    Use a Scanner(String):

    String inputLine = keyboard.nextLine();
    Scanner wordScn = new Scanner(inputLine);
    while (wordScn.hasNext())
    {
        String someWord = wordScn.next();
        // ... process someWord
    }
    

    Use String.split(String delimRegEx):

    String inputLine = keyboard.nextLine();
    String[] words = inputLine.split("\\s+");
    for (String someWord : words)
    {
        // ... process someWord
    }
    

    The "\\s+" argument to split is a regular expression that specifies the delimiter between words, meaning "white-space (\s), one or more of (+)".