Overview of This Lesson

So far, we've written programs that display output on the console. If we needed data in our program, we typed it in our source code by assigning values to our variables ("hard coding"). It is more likely that many of your inputs will come from other sources, such as a file or from the user. In this lesson we will focus on getting input from the keyboard using the Scanner class.

I'll also show you a quick technique to help you get started on basic applications: the IPO chart. You rarely ever sit down to write an application from the beginning. There's an entire design process that is followed, first. The IPO chart is a simple tool for beginners that will help you plan out your program before you start coding. Additionally, once you've completed the IPO chart, you'll see how easy it is to write the program from start to finish. This is a huge advantage for those coders who get anxiety from the blank editor and don't know where to start :)

Pre-Requisites

Before doing this lesson, make sure you are comfortable with writing arithmetic expressions, selection statements, and iteration.

IPO - Input Processing Output

The basic foundation of any program is IPO: Input-Processing-Output:

Example:

A program calculates the area of a room. Possible inputs, processing, and outputs might be:

IPO Charts

An IPO Chart is one of several tools that programmers can use when designing a program (before coding it!). An IPO chart has areas for Input, Processing, and Output, and allows you to plan out what your program needs to do.

When completing an IPO chart for a program, you actually do it in this order:

  1. Output: What is the goal of the program, what information should it produce? Why do we do this first? If you were going away on a trip, first you'd have to decide where you were going! So when designing a program, first you have to decide what it's supposed to do, what it needs to produce or show the user.
  2. Inputs: Next, decide what inputs you need in order to produce the desired output(s). What piece(s) of data are needed?
  3. Processing: We do this last, once we know the outputs and the inputs needed to determine those outputs. Here is where we decide how we create each output by transforming the input data. Typically we'd write a note about how each output is obtained.
IPO Chart Example
Inputs length of room
width of room
Processing area = length * width
Outputs area of the room

Exercises

1. Define the inputs, processing, and outputs for a program that gives the surface area and volume of a cylinder. (hint: http://math.about.com/library/blmeasurement.htm or http://www.1728.com/diamform.htm)

2. Define the inputs, processing, and outputs for a program that displays the future value of an investment for a principal P at a rate R compounded yearly for n years. The formula for compound interest is final amount = P(1+R/100)n.

1. Define the inputs, processing, and outputs for a program that gives the surface area and volume of a cylinder.

Inputs cylinder radius
cylinder height
Processing surface area = 2 * PI * radius2 + height * 2 * PI * radius
volume = height * PI * radius2
Output surface area
volume

2. Define the inputs, processing, and outputs for a program that displays the future value of an investment for a principal P at a rate R compounded yearly for n years. The formula for compound interest is final amount = P(1+R/100)n.

Inputs principal
interest rate
number of years
Processing future value = principal * (1 + rate/100)years
Output future value of investment

The Scanner Class

So far the programs you've written hard-code values into variables before the processing and output steps, but it's more advantagous (and easier to test code) to be able to get inputs from the user via the keyboard. We already know how to do output to the console or terminal window: using the println() method and the print() method.

System.out.println("Hello, World!");

Recall that System is the name of a class in Java. This class allows you to get certain information about the user's system, and it also allows you access to certain system devices. System.out gives you access to the default output device, which is the monitor. Invoking the println() method on System.out causes the value in the println() brackets (the argument) to be printed on the monitor. In the example above, the argument "Hello, World!" is printed on the monitor.

There is also an object referred to as System.in. This references the default input device. On most systems, this is the keyboard. Together, the monitor and keyboard is often referred to as the console. That's why, when we do input and output using the screen and keyboard, we call it a console program. Sometimes you'll also hear it referred to as a command-line program or command-line interface, because the input and output is occurring at the command line or prompt in a console or terminal window.

There is a special class in Java called the Scanner class. So far we've been using classes like System and String. These classes contain methods that we can use (like the String class's length() method that returns the number of characters in the string). The Scanner class is a different kind of class. You have to create a Scanner object in order to use the methods of the Scanner class. We do this by creating a variable, and instead of making the variable a primitive type (like int or double), we define it as "Scanner type":

Scanner input;

The variable here is called input, and we've declared this variable to hold Scanner objects. The identifier input follows the same standards and conventions for any variable identifier, so remember that you can call this variable anything you like as long as it follows those same rules. For example, I could have said:

Scanner scanner;

Maybe I like the variable input better, or maybe you prefer to use scanner, instead (yes, "scanner" is acceptable because it starts with a lower-case letter: it won't conflict with the name of the Scanner class).

Next, we have to construct the Scanner object and store it in the input variable:

input = new Scanner(System.in);

In this statement, the new Scanner() part of the statement constructs a new Scanner object. A Scanner object will read inputs for you, but it needs to know which device you want to read inputs from. We want it to read inputs from the keyboard, which is the default input device, so we tell it that we want it to use System.in. We do this by saying new Scanner(System.in).

If you prefer, you can put this all on one statement, instead:

Scanner input = new Scanner(System.in);

This statement says, "Create a new Scanner object that reads data from the keyboard, and then reference that Scanner object via the input variable."

Once you've created a Scanner object, you can use many of the methods that it contains. See the Scanner Documentation for a description of the class and list of methods you can use. For example, if you want to retrieve an integer from the user via the keyboard, you can do something like this:

import java.util.Scanner;
public class TestingScanner {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        System.out.print("Enter a number: ");
        int number = input.nextInt();
    }
}

Similarly, if we wanted to get a double input:

import java.util.Scanner;
  public class TestingScanner {
  
      public static void main(String[] args) {
          Scanner input = new Scanner(System.in);
          
          System.out.print("Enter a number: ");
          double number = input.nextDouble();
      }
  }

And if you wanted a String, there's a couple of ways:

import java.util.Scanner;
    public class TestingScanner {
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            
            System.out.print("Enter a sentence: ");
            String sentence = input.nextLine();
            System.out.print("Enter a word: ");
            String word = input.next();
        }
    }

We'll go over each of the more common methods in more detail as we go through this lesson.

Getting Input Using Scanner

To use the Scanner to obtain input, we have to use the Scanner's instance methods. Instance methods are methods that you execute/invoke on an instance of the class; you must use an object variable that references a Scanner object to call on the Scanner's methods. This is different from static methods: Static methods are methods that you execute/invoke upon the name of the class. For example, to use the Math class's pow() method, you have to call it with Math.pow(a, b). With instance methods, you must first construct an instance of a class (create an object from that class) and then use that object to execute/invoke the methods.

So, in order to use the Scanner's instance methods, you must first construct a Scanner object as described in the previous section:

Scanner input = new Scanner(System.in);

Most of the Scanner object's instance methods (such as next(), nextInt(), and nextDouble()) will read in data until they reach any "whitespace" character or characters. This includes spaces, tabs, and new-lines.

The Scanner's nextLine() method is a big different: it will read all the characters including tabs and spaces, but will stop reading when it encounters the newline character.

One problem with this difference is when you want to use both the nextLine() method in the same program as the other input methods. Try the following program to understand the problem:

import java.util.Scanner;

public class  TryScanner {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        System.out.println("Enter an integer: ");
        int num = input.nextInt();
        System.out.println("Your int: " + num);

        System.out.println("---------");
        System.out.println("Enter a floating-point value:");
        double num2 = input.nextDouble();
        System.out.println("Your floating-point: " + num2);

        System.out.println("---------");
        System.out.println("Now enter a string.");
        String str = input.nextLine();
        System.out.println(str);
    }
}

When you run the program, you'll get the following:

Enter an integer: 
23
Your int: 23
---------
Enter a floating-point value
2.5
Your floating-point: 2.5
---------
Now enter a string.

Press any key to continue . . .

When the program runs, the prompt to enter a string appears but there is no opportunity to enter anything!

What if we use the next() method instead of nextLine()? Change the last section of your code:

import java.util.Scanner;

public class  TryScanner {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        System.out.println("Enter an integer: ");
        int num = input.nextInt();
        System.out.println("Your int: " + num);

        System.out.println("---------");
        System.out.println("Enter a floating-point value:");
        double num2 = input.nextDouble();
        System.out.println("Your floating-point: " + num2);

        System.out.println("---------");
        System.out.println("Now enter a string.");
        String str = input.next();
        System.out.println(str);
    }
}

This time, we get something like:

Enter an integer: 
23
Your int: 23
---------
Enter a floating-point value
2.5
Your floating-point: 2.5
---------
Now enter a string.
Hi there!  How are you?
Hi
Press any key to continue . . .
        

This time, we were allowed to enter a string, but only the first word in the string was saved to the variable. That's because the next() method stops "recording" at the first space.

But why didn't nextLine() work? The nextLine() method is supposed to stop recording when it sees a new-line (enter key). The problem is not actually with nextLine(). The problem is actually the previous calls to Scanner's methods.

When a user types values using the keyboard, each keystroke is stored in the input buffer. The input buffer is an area of memory that the Scanner object uses to "record" input values. Whenever you use one of the Scanner's methods, it goes to the input buffer and reads back the values stored there. As it reads a value, that value is removed from the input buffer. To see how this works, try the following:

import java.util.Scanner;

public class  TryScanner {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        System.out.println("Enter an integer, then a " +
                "double, then type some text.");
        int input = keysIn.nextInt();
        double dblNum = input.nextDouble();
        String strText = input.nextLine();

        System.out.println(intNum);
        System.out.println(dblNum);
        System.out.println(strText);
    }
}

When the program runs, type:
23 4.5234 This is some other text
Then press the ENTER key. Your output should appear as:

Enter an integer, then a double, then type some text,
23 4.5234 This is some other text
23
4.5234
This is some other text
Press any key to continue . . .
        

Once you enter the complete line of values, they are stored in the input buffer. When you call nextInt(), the Scanner object goes to the input buffer and reads back an integer value. That value (23) is then removed from the buffer, because it has been processed by the Scanner. When nextInt() is executing, it takes all the characters it finds until it encounters a white-space character (such as tab, space, or new-line). Then it takes those characters and parses or converts them into an int value. It does not take the white-space character that indicates the end of the int value, so that space is still in the buffer after nextInt() executes.

Then you call the nextDouble() method. The Scanner goes back to the input buffer and sees a space, and a double value terminated by the next white-space character (a space, in this case). The Scanner object understands that the first space was just a delimiter or separator that divided the previous value from the current one, so it tosses that away. Then it reads the 4.5234 as a double, stopping at the next space, and stores it in the dblNum variable. Finally, it removes the double value from the input buffer. What's now left in the input buffer is the second space, and the string "This is some other text" followed by a new-line character.

The nextLine() method is called, and the Scanner goes to the input buffer. It knows that the nextLine() method is a bit different. The other methods will stop at any whitespace because it recognizes whitespace characters as delimiters. However, the nextLine() method will read in all the values until it finds a new-line character. Therefore, the newLine() method, when called, goes to the input buffer and grabs the space and the text that comes after it. It then finds the new-line, so it knows to stop taking characters. The characters are all removed from the input buffer, and so is the new-line, although the new-line is thrown away - it is not stored as part of the rest of the string.

1. When nextInt() is executed, it reads back the integer value and stores it in the intNum variable. Then the integer value is removed from the input buffer.

an input buffer containing the sample text, 23 being read and stored in intNum
1. nextInt() reads the integer into intNum

2. The input buffer now contains a space, a double, and some text. When nextDouble() is executed, it knows the space is the delimiter, so the space is discarded. Then it reads the double value and stores it in the variable dblNum. The double value is then removed from the input buffer.

the input buffer, now only showing the floating point value and text; the floating point value is copied into dblNum
2. nextDouble() reads discards whitespace and reads the double value

3. Now the input buffer contains a space (the delimiter between the double and the text), and the rest of the text ("This is some other text"). The nextLine() method uses the new-line as the delimiter, so it removes all the text from the input buffer and stores it in the strText variable. It stops at the new-line. Then it takes the new-line out of the buffer and discards it.

the input buffer now only contains the text and the new-line at the end, the text is copied into strText
3. The rest of the data up to the newline is read into a string variable

Now run the program again, but this time follow each input value by pressing the enter key. In other words, run the program and type:

23 [press enter]
4.5234 [press enter]
This is some other text  [press enter]

What you'll find is that after entering the double value, you are not given an opportunity to press the Enter key! This is because of the way the methods work as described above. nextInt() will take the int and stop at the first whitespace character(s), which in this case is the new-line you pressed after entering 23. Then nextDouble() executes and sees a new-line left there from the previous statement. It considers this new-line as whitespace, so it tosses it away. Then it takes the double that comes next, stopping at the 2nd new-line you pressed after entering 4.5234. It leaves this new-line in the buffer.

The nextLine() method executes next, and it sees the new-line that came after the double value. It knows it's supposed to take all data until it comes to the new-line and then quit. Well, it encountered a new-line right away, so it takes it, tosses it away, and then quits.

So what do we do to solve this problem? There are a couple of solutions. In other language, you could clear the input buffer of the new-line after you read the last numeric value. In Java, the Scanner class doesn't have a method that does this for you. Instead, you could just call the nextLine() method to toss away the new-line, then call it again to read in the line of text:

Scanner keysIn = new Scanner(System.in);

System.out.println("Enter an integer, then a " + 
"double, then type some text.");
int intNum = input.nextInt();
double dblNum = input.nextDouble();

// toss the last new-line:
input.nextLine();

// now read the actual string:
String strText = input.nextLine();

System.out.println(intNum);
System.out.println(dblNum);
System.out.println(strText);

When you run the modified program and press enter after each input, you'll get something like:

Enter an integer, then a double, then type some text.
23
2.5
This is a line of text.
23
2.5
This is a line of text.

This works! Some programmers might not be happy with this solution, however. One alternative is to "reset" the Scanner object before you grab the line of text. To reset the Scanner object, you just redefine it using the same Scanner variable: input = new Scanner(System.in); This will also clear the input buffer of any input data that was left over:

Scanner input = new Scanner(System.in);

System.out.println("Enter an integer, then a " +
"double, then type some text.");
int intNum = input.nextInt();
double dblNum = input.nextDouble();

// reset the scanner
input = new Scanner(System.in);
// now read the actual string:
String strText = input.nextLine();

System.out.println(intNum);
System.out.println(dblNum);
System.out.println(strText);

When you run the program, you should get the same output as the previous example.

A second alternative is to always capture your input using the nextLine() method, then you never have to worry about extra characters in the input buffer. For example:

Scanner input = new Scanner(System.in);

System.out.print("Enter an integer: ");
String strInteger = input.nextLine();
System.out.print("Enter a double: ");
String strDouble = input.nextLine();
System.out.print("Type some text: ");
String strText = input.nextLine();

System.out.println(strInteger);
System.out.println(strDouble);
System.out.println(strText);

This program works just fine. However, what if you wanted to perform calculations on your numeric values? You can't calculate with a String! In this case, we would need to convert our String values into ints and doubles.

In Java, there are some special classes called wrapper classes that are associated with each primitive type. For example, the wrapper class for the int primitive type is called Integer, and the wrapper class for the double primitive type is called Double. These wrapper classes contain methods that you can use to convert Strings into primitive types: they're called the "parse" methods. For example:

// converts strValue into an int and stores in intValue
int intValue = Integer.parseInt(strValue);
// converts strValue into a double and stores in dblValue
double dblValue = Double.parseDouble(strValue);

In the first statement, we call on the parseInt() method in the Integer class and give it strValue as an argument/input. We can assume here that strValue is a String variable. The Integer.parseInt() method then converts strValue into a primitive int value and stores that result into the variable intValue.

In the second statement, we call on the parseDouble() method in the Double class and give it strValue as an argument/input. Again, this example assumes strValue is a String variable. The Double.parseDouble() method converts strValue into a primitive double and stores that result into the variable dblValue.

You can use either of these methods to convert user-input values into the appropriate data type. For example:

Scanner input = new Scanner(System.in);

System.out.print("Enter quantity: ");
String strQty = input.nextLine();
intQty = Integer.parseInt(strQty);
System.out.print("Enter price: ");
String strPrice = input.nextLine();
dblPrice = Double.parseDouble(strPrice);
System.out.print("Enter description: ");
String strDescrip = input.nextLine();

double total = intQty * dblPrice;

System.out.println("Total for " + strDescrip + ": " 
+ total);

One thing to note about using Integer.parseInt() and Double.parseDouble() is that they will crash if they attempt to parse anything that isn't a valid int or double. For integers, this means anything that isn't a digit (so any value with letters, symbols including the decimal point and comma, or even the null-string ("") will cause the program to crash). For double values this means only digits and one decimal point are allowed; any commas, letters, symbols, multiple decimal points, and the null-string will cause the program to crash.

In a later lesson, you'll learn how to validate the user's input before you parse it, so that the program won't crash! In fact, you'll even be able to give the user a nice error message and even prompt them to try entering the value again. :)

Exercises

1. Copy the code below into a main() method of a new program, and fill in the missing code by following the instructions in the comments:

public class ScannerExercise {

    public static void main(String[] args) {

        // construct a scanner to get keyboard input

  
        // ask the user for a decimal number
        // (add the stmt to retrieve the value and store in an
        // appropriate variable) 
        System.out.print("Enter a decimal number: ");

  
        // calculate the number times itself (the square)
        // and store in an appropriate variable (which needs
        // to be declared - see last statement below where
        // the variable is being used) 
  

        // user wants to see the result, this is finished so
        // nothing to do here unless you used different variable name)
        System.out.println("Your number squared is "
                + square);
    }
}
Question 1. Fill in the missing code

The following exercises will help us put together everything we've learned so far about writing Java programs.

2. For each of the programming questions below, draw up an IPO chart outlining the inputs, processing, and outputs each program solution requires. Then write a program that gets the user inputs using the Scanner class. Display your outputs on the console.

  1. Develop a solution for a program that converts a temperature from Fahrenheit to Celsius. (Celsius temperature = 5.0/9.0 * (Fahrenheit temperature - 32.0).
  2. Develop a solution for a program that calculates a person's target heart rate (a target heart rate is the heart rate you should aim to maintain while you're working out). Use the following formula: Target Heart Rate = .7 * (220 - your age) + .3 * Resting Heart Rate (your resting heart rate is your heart rate while you're not participating in any physical activity).
  3. Write a tip calculator that allows a restaurant or bar customer to calculate the amount of a tip to give their wait person. The program should allow the customer to specify the bill amount and the percentage of tip they would like to give.
  4. The three ingredients required to make a bucket of popcorn in a movie theatre are popcorn, butter, and a bucket. Write a program that requests the cost of these three items and the price of a serving of popcorn (assume we have only one size). The program should then display the profit.
  5. You would like to be able to calculate your average grade for all the courses you've taken in first semester. Write a program that prompts you for the grades for the five courses you would have completed in first term. After recording all five grades, display the average grade on the console.

    Sample output using sample data:

    You entered your five grades as:  85.6 78.9 75.5 90.0 86.5
    Your average grade:  83.3

a) Develop a solution for a program that converts a temperature from Fahrenheit to Celsius. (Celsius temperature = 5.0/9.0 * (Fahrenheit temperature - 32.0).

Input Fahrenheit temperature
Processing celsius = 5.0/9.0 * (fahrenheit - 32.0)
Output Celsius temperature
code solution 2a
Question 2. a) temperature conversion

b) Develop a solution for a program that calculates a person's target heart rate (a target heart rate is the heart rate you should aim to maintain while you're working out). Use the following formula: Target Heart Rate = .7 * (220 - your age) + .3 * Resting Heart Rate (your resting heart rate is your heart rate while you're not participating in any physical activity).

Input resting heart rate
age
Processing target heart rate = .7 * (220 - age) + .3 * resting heart rate
Output target heart rate
code solution 2b
Question 2. b) target heart rate

c) Write a tip calculator that allows a restaurant or bar customer to calculate the amount of a tip to give their wait person. The program should allow the customer to specify the bill amount and the percentage of tip they would like to give.

Input bill amount, tip percentage
Processing tip amount = tip percentage / 100 * bill amount
Output tip amount
code solution 2c
Question 2. c) tip amount

d) The three ingredients required to make a bucket of popcorn in a movie theatre are popcorn, butter, and a bucket. Write a program that requests the cost of these three items and the price of a serving of popcorn (assume we have only one size). The program should then display the profit.

Input cost of bucket
cost of butter
cost of popcorn
selling price
Processing profit = selling price - (cost of bucket + cost of butter + cost of popcorn)
Output profit for one bucket of popcorn
code solution 2d
Question 2. d) popcorn profit

e) You would like to be able to calculate your average grade for all the courses you've taken in first semester. Write a program that prompts you for the grades for the five courses you would have completed in first term. After recording all five grades, display the average grade on the console.

Sample output using sample data:

You entered your five grades as:  85.6 78.9 75.5 90.0 86.5
Your average grade:  83.3
Input course 1 grade
course 2 grade
course 3 grade
course 4 grade
course 5 grade
Processing average grade = (course 1 grade + course 2 grade + course 3 grade + course 4 grade + course 5 grade) / 5
Output list of grades input
average grade
code solution 2e
Question 2. e) average grade