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 :)
The basic foundation of any program is
IPO:
Input-Processing-Output:
Input consists of the data that goes into the
program. Most programs need to have data to work with,
so as a programmer you need to decide how the input
gets into the program. Is it typed in by the user?
Is it read from a file?
Processing is what happens to the data inside
the program. This is where a lot of your code will
be doing the most work, especially in larger programs. Sometimes
there are many different kinds of processing tasks
going on in the same program. Such tasks include
calculating, manipulating text or numeric data,
searching, sorting, and comparing.
Output is the end result of your program, or
the results of the processing. The inputs are
transformed into outputs by the processing tasks
that have been performed. The programmer also needs
to decide what form the outputs will take. For
example, are they displayed on the screen, printed
with a printer, or saved to a file?
Example:
A program calculates the area of a room.
Possible inputs, processing, and outputs might be:
Inputs: length of the room, width of the room
Processing: calculate the area using
length and width
Output: the area of the room
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:
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.
Inputs: Next, decide what inputs
you need in order to produce the desired output(s).
What piece(s) of data are needed?
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.
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.
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.
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.
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:
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);
}
}
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.
Develop a solution for a program that converts
a temperature from Fahrenheit to Celsius. (Celsius
temperature = 5.0/9.0 * (Fahrenheit temperature - 32.0).
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).
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.
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.
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
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).
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
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
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