Welcome to Lesson 15!


Learning Objectives
By the end of today's class, you should know...
  • What is a do-while loop?
  • What is the syntax of a do-while loop?
  • When do you use a do-while loop instead of a while loop?
  • How do you use loops to prevent type mismatch exception?
    • hasNextDouble()
    • hasNextInt()

Announcements

  • Last day to drop with a "W" is this Friday.
    • Check your current grade on Canvas
    • In most cases, it is better to get a 'W' rather than have an 'F' on your transcript
    • Feel free to talk your decision over with me
  • Quiz 6 next class
  • Return Quiz 5
  • Don't forget to complete Lab 8 on Friday


Review Activity:

With a partner, answer the following questions:

  • Write a for loop to print the following String named sport out character-by-character:
String sport;
System.out.println("Enter your favorite sport: ");
sport = input.next();
//write your for loop here

  • What will the following display to the console?

String message = "I love cookies!";

    System.out.print(message.substring(8, 10));

Wrapping Up Strings

  • When you press the Enter key, a newline character ('\n') is inserted as part of the input
  • The newline character can cause problems when you mix input.next(), input.nextInt() or input.nextDouble() with input.nexLine()
  • Recall that input.next(), as well as nextInt() and nextDouble():
    1. Skips whitespace
    2. Reads non-whitespace characters into the variable
    3. Stops reading when whitespace is found
  • Since whitespace includes newline characters, using input.next() will leave a newline character in the input stream
  • However, input.nextLine() just stops reading when it first finds a newline character
  • This can lead to mysterious results in code like the following:
    System.out.print("Enter your age: ");
    int age = input.nextInt();
    System.out.print("Enter your full name: ");
    String name = input.nextLine();
    System.out.println("Your age: " + age + "\n"
         + "Your full name: " + name);
    
  • To correct this problem we add an additional input.nextLine() just before input.nextLine()

System.out.print("Enter your full name: "); 
input.nextLine(); //clear out the \n
String name = input.nextLine();

  • We can see how to use this fix in the following example

Example Using an additional input.nextLine()


public static void main(String[] args) {
    Scanner input = new Scanner(System.in);

    System.out.print("Enter your age: ");
    int age = input.nextInt();

    System.out.print("Enter your full name: ");
    input.nextLine(); //clear out the \n
    String name = input.nextLine();     System.out.println("Your age: " + age + "\n"     + "Your full name: " + name); }

  • Often, loops can make it more difficult to detect when an extra input.nextLine() will be required.
  • For example, the below loop seems to contain an input.nextLine() followed by an input.nextInt() statement.
  • However, the looping behavior alters the order of the two statements.

Example Using an additional input.nextLine()


public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int num = 1;
        String repeat = "y";
        while (num <= 10) {
            System.out.print("Enter the name of student " + num + ": ");
            String student = input.nextLine();

            System.out.print("Enter the id number of student " + num + ": ");
            int id = input.nextInt();
            System.out.println("\nStudent " + num + " name: " + student);        
            System.out.println("Student " + num + " id: " + id + "\n");

            num++;
            input.nextLine(); //to account for input.nextLine() at next iteration of loop     
        }
 }


Activity 15.1: Sentence Continued (10 pts)
  • Let's add to our program involving sentences from the last activity. We will also calculate the number of letters in the sentence and take in a user guess for a number of letters.
  • At the end of the program, we will confirm whether their guess was correct or not.
  • Declare a new variable beneath the other two at the top of the program. This variable will be used to store our calculation for the number of letters. 
  • Also, add a variable to store the user input for their guess. 
  • The variable declaration section of your program should now look like this:
String sentence;
int numWords = 1;
int numLetters = 0;
int start_index = 0;
int guess;
Scanner input = new Scanner(System.in);
  • Now alter your first System.out.println statement to reflect the additional uses of this program. Remove the original message in your System.out.println statement and replace it with the one below:
Think of a sentence in your mind.
Later I will tell you how many words and letters are in your sentence.

  • Now, ask the user to enter a guess for how many letters are in the sentence. We want the user to guess without counting the number of letters.
Enter a guess for the number of letters in your sentence (don't count!): _
  • Store the user guess as the guess variable using input.nextInt().
  • Next, prompt the user to enter the sentence. Your prompt should remain the same from the last exercise and, as before, you should use input.nextLine() to store the user input as the sentence variable.
Please enter your sentence: _
  • Verify that your code inside main looks like identical to the code below:

  • Now, run your program. You should notice a problem.
  • How can we fix this problem?
  • Add an additional input.nextLine() above your sentence = input.nextLine();
input.nextLine();
sentence = input.nextLine();
  • Compile and run your code again and verify that it is now working properly.
  • Now let's alter the code inside the for loop to calculate how many letters are in the sentence.
  • Since we don't want to count any blank spaces, we only want to increment the numLetters variable when we are NOT incrementing the numWords variable. 
  • Therefore, we need to add an else statement to our for loop. Make sure your if-else in the for loop looks like this:
if (sentence.charAt(i) == ' ') {
    numWords++;
    System.out.println(sentence.substring(start_index, i));
    start_index = i+1; //new starting index
} else {
    numLetters++;
}
  • Now, let's add another print statement below the for loop to print out the number of letters in the sentence,
System.out.println("And, " + numLetters + " letters.");
  • Did our user guess the number of letters correctly? Now is the time to let him or her know. Add the following if-else block at the bottom of main.
if (guess == numLetters) {
    System.out.println("You guessed right!");
} else {
    System.out.println("You guessed wrong!");
}
  • Run your program again and you should get the following output. Note: if you don't get the output below, compare your program to the final version at the end of this exercise. When you are finished, upload to Canvas.

  • The revised portion of your code should look like the following:



Do-While Loops

  • Sometimes we want to execute the body of a loop at least once and perform the loop test after the body was execute
  • In this case, we can use a do-while loop (a.k.a. do loop).
  • The structure of a do-while loop looks like this
    do {
       //statements
    } while (test); // loop test
    
  • Where:
    • statements: the statements to execute the first time and repeatedly while the test remains true
    • test: the test condition to evaluate
  • The loop test is placed after the body and executes at the end of the loop
  • The statements in the body of the loop always execute at least once

Flowchart of do-while loop:

Flowchart of working of do...while loop in C programming.

Image source.

  • One common use of a do-while loop is to validate user input
  • The following code shows an example where we force the user to enter a positive value

Example do-while Loop Used to Validate Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package loopy;

/**
*
* @author Jennifer Parrish
*/
import java.util.Scanner;

public class Loopy {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
double value;
Scanner input = new Scanner(System.in);
do {
System.out.print("Enter a positive number: ");
value = input.nextDouble();
} while (value <= 0.0); // test condition at end
System.out.println("You entered: " + value);
}
}

When to Use do-while Statements

  • Use the do-while loop when you want to force a minimum of one iteration
  • Note that you can accomplish the same control flow with a while loop
  • However, in some cases we can save a statement by using a do-while loop

Group Activity
With a partner, answer the following questions:
  • How is the syntax of a do-while loop different from a while loop?
  • When would you use choose a do-while loop over a while loop?
  • Change the following while loop into a do-while loop:
int score, sum = 0;
System.out.print("Enter a score or 0 to quit: ");

score = input.nextInt();

while (score != 0)
{
    sum += score;
    System.out.print("Enter a score or 0 to quit: ");

    score = input.nextInt();
}
System.out.println("The sum is: " + sum);
   


Loops and Error Checking

Using Loops to Check for input mismatch

  • A problem arises if the user of a our programs enters a String when we expect a number
  • For instance, in the following, we get incorrect results if the user enters "seven"
    double value = 0.0;
    ...
    value = input.nextDouble(); //user enters "seven" not 7
    
  • The problem is that Scanner cannot convert the word "seven" into the number 7
  • When this happens the code crashes with an error message about an input mismatch exception:
  • When the program suddenly crashes, the user will be confused.
  • Also the rest of the program cannot proceed.
  • A better approach would be to anticipate the possibility of the above user error and handle it in our code.
  • We can detect the failure condition using code like the following:

            double value = 0.0;
       Scanner input = new Scanner(System.in);
       System.out.print("Enter a positive number: ");
       
       if(input.hasNextDouble()) { //Check to see if the user entered a double
           value = input.nextDouble(); //read in the double
       }
       else {
           System.out.println("Error! Please enter a number not text!");
           input.nextLine(); //read in the String value from the user to clear it from buffer
       }

  • Depending on the expected input, we can use one of the following functions to test for input mismatch:
hasNextInt() //returns true if the user entered an int
hasNextDouble() //returns true if the user entered a double
  • Both functions will return true if the user entered the correct type and false otherwise.
  • However, there is a problem with the above approach?
    • What happens if the user enters the incorrect type more than once?
  • Let's use a loop instead!

Example Program with Input Validation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

package loopy;

/**
*
* @author Jennifer Parrish
*/
import java.util.Scanner;

public class Loopy {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
double value = 0.0;
Scanner input = new Scanner(System.in);
System.out.print("Enter a number: ");

while(!input.hasNextDouble()) { //Check to see if the user entered a double
System.out.println("Error! Please enter a number not text!");
input.nextLine(); //read in the String value from the user to clear it from buffer

System.out.print("Enter a number: "); //prompt again
}
value = input.nextDouble(); //read in the double
System.out.println("You entered " + value);
}
}
More information on hasNextDouble() and hasNextInt() methods


Activity 15.3: Scores (10 pts)

  • In this exercise we use indefinite loops to process user input and to ensure correct user input.
  • Find a partner for pair programming.
  • Open a new Eclipse project named Scores.
  • Declare two variables of type double named sumScores and nextScore and initialize the variables to 0. In addition, declare an integer variable named count and initialize it to 0. The following is the psuedocode for these steps:
    set sumScores to 0
    set nextScore to 0

    set count to 0
  • Compile your code to make sure you declared the variables correctly.

  • Now we want to use a loop to enter a series of scores. Since we do not know how many scores to enter, we use an indefinite loop like the following:

  • In addition, add a statement to display sumScores after the loop.

    Compile your code to make sure you added the loop correctly. To exit the loop you will need to enter a negative number.

  • The loop includes statements to collect the sum of the scores in the variable named sumScores. Add a statement after the loop to print sumScores to the console. When you run the program after adding this code, the output should look like:
    Enter score #1: 60
    Enter score #2: 50
    Enter score #3: 20
    Enter score #4: 99
    Enter score #5: 100
    Enter score #6: 0
    Enter score #7: 45
    Enter score #8: 86
    Enter score #9: -1

    Sum of scores: 460.0

    The loop uses the sumScores variable to accumulate scores during each repetition of the loop. 

  • We could write our indefinite loop using a do-while loop instead. Replace your current loop with the following:

  • Note that the statements inside the loop did not change, only the loop statement itself. To make sure you made the changes correctly, compile and run your code and check to see if it works the same. The difference between a while and do-while loop is that a do-while ensures the body of the loop is executed at least once. 

  • One problem with our program is the user can still enter letters instead of digits. We can prevent this error by checking input.hasNextDouble() and looping until the user enters a correct value. Replace the current if statement with the following and move the nextScore = input.nextDouble()inside of an else statement as shown below:
The completed program

  • Compile and run your program to make sure you added the changes correctly. Try entering letters instead of digits and verify you see an error message.

Enter score #1: seventy
Error! Please enter a number, not text.
Enter score #2: 79
Enter score #3: 80
Enter score #4: twenty
Error! Please enter a number, not text.
Enter score #5: Error! Please enter a number, not text.
Enter score #6: 20
Enter score #7: 0
Enter score #8: -1

Sum of scores: 179.0
  • Note that when you report the error message and ask the user to try again, the count variable gets off track. There are two approaches to fixing this problem.
    • With your partner, try to find at least one solution to this problem.
  • When finished, upload your Scores.java file to Canvas.



Wrap Up

  • With your partner, answer the questions from today's learning objectives


Upcoming Assignments
  • Assignment 15 due Thursday at 1:20pm on Canvas
  • Lab 8 due Friday at midnight