University College of Applied SciencesProgramming 1
العربية
Lecture 5 · 100 min

Keyboard Input with Scanner

Today, for the first time, your program stops and waits for what you type.

By the end of this lecture you will be able to

  1. Explain the roles of input, processing and output in any program
  2. Set up Scanner with an import and new, and read from the keyboard with it
  3. Choose the right read method for each data type, and read a single character when needed
  4. Write a clear prompt before every read
  5. Diagnose and fix the trap of nextInt followed by nextLine
  6. Explain InputMismatchException and write calculation programs that interact with the user
In this lecture
  1. Until today, every program you wrote gives the same answer on every run
  2. Now your program stops and waits for you
  3. Three lines connect your program to the keyboard
  4. Each data type has its own read method
  5. A prompt tells the user what to type
  6. next reads a word, and nextLine reads the rest of the line
  7. There is no nextChar, so we take the first character of a word
  8. nextInt leaves the Enter behind, and nextLine picks it up
  9. The fix: consume the Enter with an extra nextLine
  10. If the user types text instead of a number, the program stops with an exception
  11. A calculator: two inputs and four operations
  12. Rectangle area: start by asking what the inputs are
  13. Temperature conversion: one formula for any value the user types
  14. Final exercise: a student card from the keyboard
  15. Review questions
Part one: the program listens to you

Until today, every program you wrote gives the same answer on every run

Every value so far is one we wrote inside the code ourselves. Run the next program ten times and it greets Sara ten times. To greet anyone else, you must open the code and change it.

A program that only knows Sara

Run it twice. Could someone who knows no Java make it greet them by name?

public class FixedGreeting {
    public static void main(String[] args) {
        String name = "Sara";
        System.out.println("Hello, " + name + "!");
    }
}
Output
Hello, Sara!
Input

What comes from outside the program: an amount you type at a cash machine, or a student's marks.

Processing

What the program does with the values: checks the balance, or calculates the average.

Output

What the program shows: the cash and receipt, or the final average.

Now your program stops and waits for you

This is a special moment in your journey: the next program does not know its answer when you press Run, because part of that answer is still with you.

Your first program that listens

Press Run. The program stops and an input box appears. Type your name and press Enter. Then run it again with a classmate's name: the same code, a different answer.

import java.util.Scanner;

public class Greeting {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("What is your name? ");
        String name = input.nextLine();
        System.out.println("Hello, " + name + "!");
    }
}

Three lines connect your program to the keyboard

Import

Scanner is a ready-made class in the java.util package. Write this line at the top of the file, before class and after package if there is one.

import java.util.Scanner;
Create

Make one reader and name it. System.in means the keyboard. The name input is our choice.

Scanner input = new Scanner(System.in);
Read

Ask the reader for the next value and put it in a variable of the right type.

int age = input.nextInt();

The compiler does not know Scanner

We forgot one line. Add it so the program works.

public class Ready {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Scanner is ready");
    }
}
Compiler messagecannot find symbol
Show the fix
import java.util.Scanner;

public class Ready {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Scanner is ready");
    }
}
Output
Scanner is ready

Why? Scanner is not among the basics the compiler knows automatically. The message says it cannot find the symbol and never mentions an import, so remember this cause whenever you see it with Scanner.

Read from where?

We created the reader without telling it where to read from.

import java.util.Scanner;

public class Ready {
    public static void main(String[] args) {
        Scanner input = new Scanner();
        System.out.println("Scanner is ready");
    }
}
Compiler messageno suitable constructor found for Scanner(no arguments)
Show the fix
import java.util.Scanner;

public class Ready {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Scanner is ready");
    }
}
Output
Scanner is ready

Why? Scanner needs a source to read from and does not pick the keyboard by itself. The message is long and scary, but "no arguments" says it all: you gave it nothing between the parentheses.

Each data type has its own read method

MethodReadsTypeUser types
nextInt()A whole numberint19
nextDouble()A decimal numberdouble3.75
next()One word, up to the first spaceStringSara
nextLine()The whole line, spaces includedStringSara Ali
nextBoolean()true or falsebooleantrue

Four reads in one program

Run the program and answer each question. Notice that the program stops at each read, in order.

import java.util.Scanner;

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

        System.out.print("Age: ");
        int age = input.nextInt();
        System.out.print("GPA: ");
        double gpa = input.nextDouble();
        System.out.print("City: ");
        String city = input.next();
        System.out.print("Passed (true or false): ");
        boolean passed = input.nextBoolean();

        System.out.println("Age: " + age);
        System.out.println("GPA: " + gpa);
        System.out.println("City: " + city);
        System.out.println("Passed: " + passed);
    }
}

Which method fits reading a book price such as 12.5?

You want to read a full address such as 12 Omar Street. Which method fits?

A prompt tells the user what to type

Scanner prints nothing. If you print no message before the read, the user faces a silent program and has no idea what it wants.

A silent program

Run it as if you had never seen the code: what do you type? Then add a message before each read using print, such as "Length in metres: ".

import java.util.Scanner;

public class Silent {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double length = input.nextDouble();
        double price = input.nextDouble();
        System.out.println(length * price);
    }
}

We prefer print for prompts because it leaves the cursor on the same line, so the user types beside the question. println moves to a new line.

Both styles together

This lab gives the program the values 19 and 3.5 automatically. Compare how the two prompts look in the output.

import java.util.Scanner;

public class Prompts {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Enter your age:");
        int age = input.nextInt();
        System.out.print("Enter your GPA: ");
        double gpa = input.nextDouble();
        System.out.println("Age " + age + ", GPA " + gpa);
    }
}
Output
Enter your age:
Enter your GPA: Age 19, GPA 3.5

next reads a word, and nextLine reads the rest of the line

Picture what you type as a strip of characters passing in front of Scanner. Each read takes a piece of the strip and moves on. Whatever is not read stays there for the next read.

The user typed Sara Ali Omar then Enter. What does the program print?

import java.util.Scanner;

public class Words {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String first = input.next();
        String rest = input.nextLine();
        System.out.println("[" + first + "]");
        System.out.println("[" + rest + "]");
    }
}
Show the output
Output
[Sara]
[ Ali Omar]

Why? next takes the first word and stops before the space, so nextLine starts at that space and takes the rest. The square brackets reveal a space your eyes would otherwise miss.

Try it yourself

Run it and type a two-word name. Then change next to nextLine and run it again with the same name.

import java.util.Scanner;

public class WordOrLine {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Full name: ");
        String name = input.next();
        System.out.println("Welcome, " + name);
    }
}

There is no nextChar, so we take the first character of a word

char grade = input.next().charAt(0);
next() gives a string, and charAt(0) takes the character at position 0, the first one.

Read a grade

Run it and type B. Then run it and type Excellent. Then change 0 to 1 and run it again with Excellent.

import java.util.Scanner;

public class Grade {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Your grade: ");
        char grade = input.next().charAt(0);
        System.out.println("Grade stored: " + grade);
    }
}

The user typed Hello. What does the program print?

import java.util.Scanner;

public class FirstLetter {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        char letter = input.next().charAt(0);
        System.out.println(letter);
    }
}
Show the output
Output
H

Why? The 0 is the position of the character, not what gets printed. A char holds only one character, so H stays and the rest of the word is ignored.

A string in a char box

This is what happens if you write char grade = input.next();. Fix it so the program prints A.

public class CharBox {
    public static void main(String[] args) {
        String word = "A";
        char grade = word;
        System.out.println(grade);
    }
}
Compiler messageincompatible types: String cannot be converted to char
Show the fix
public class CharBox {
    public static void main(String[] args) {
        String word = "A";
        char grade = word.charAt(0);
        System.out.println(grade);
    }
}
Output
A

Why? Even a one-letter string is still a String. The compiler does not turn it into a char for you; you must take the character out with charAt(0).

Part two: traps and errors

nextInt leaves the Enter behind, and nextLine picks it up

This is the most famous Scanner trap, and every one of you will fall into it once. The code looks perfectly correct and compiles without error. Try it first: type your age, press Enter, and wait for the name question.

The program that does not wait

Run it. Did you get a chance to type your name?

import java.util.Scanner;

public class Trap {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.println("[" + name + "] is " + age);
    }
}

The input here is two ready lines: 19 then Sara Ali. What does the program print?

import java.util.Scanner;

public class Trap {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.println("[" + name + "] is " + age);
    }
}
Show the output
Output
Age: Name: [] is 19

Why? nextInt took only the digits 19. The Enter stayed on the strip, so nextLine found it at once and took it as the end of an empty line. Nobody read Sara Ali.

ReadWhat it takesWhat stays on the strip
nextInt()19The Enter, then Sara Ali
nextLine()Nothing but the EnterSara Ali, which nobody reads

The fix: consume the Enter with an extra nextLine

We add one line after nextInt that takes the Enter and throws it away, without saving it in any variable. The strip is then clean, and nextLine waits for the real name.

The fix with the same input

The input is ready: 19 then Sara Ali. Compare the output with the previous one.

import java.util.Scanner;

public class TrapFixed {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        input.nextLine(); // Throw away the Enter left by nextInt
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.println("[" + name + "] is " + age);
    }
}
Output
Age: Name: [Sara Ali] is 19

Now you type

Run it and type your age and full name. This time the program waits for you. Press "Debug line by line" and watch where it stops at each read, then delete the extra line and compare.

import java.util.Scanner;

public class TrapFixedLive {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        input.nextLine();
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.println("Hello " + name + ", you are " + age);
    }
}
First readNext readA trap?
nextInt()nextInt()No: it skips the Enter
nextInt()next()No: it skips the Enter
nextDouble()nextLine()Yes: the same trap
next()nextLine()Yes: the same trap
nextLine()nextInt()No: nextLine takes its Enter along

Which order needs an extra nextLine between the two reads?

Age, then name

Print the prompt Age: and read a whole number, then print the prompt Name: and read a whole line, then print Sara Ali is 19 using the values you read.

import java.util.Scanner;

public class AgeThenName {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the age, then the full name, then print the sentence

    }
}
stdin
19
Sara Ali
Expected output
Age: Name: Sara Ali is 19
Hint 1

If the name comes out empty, you fell into the trap.

Hint 2

Add input.nextLine(); right after nextInt.

Solution
import java.util.Scanner;

public class AgeThenName {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        input.nextLine();
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.println(name + " is " + age);
    }
}

If the user types text instead of a number, the program stops with an exception

The compiler checks the code before it runs, but it cannot know what the user will type later. So this error appears only while running, and it is called an exception. Let us cause one on purpose.

Break the program on purpose

Run it and type 19. Then run it and type abc, and read the explanation shown under the output. Then try 19.5: what do you expect?

import java.util.Scanner;

public class BreakIt {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("How old are you? ");
        int age = input.nextInt();
        System.out.println("Next year you will be " + (age + 1));
        System.out.println("Goodbye");
    }
}

The user typed abc. What appears in the normal output, leaving the error message aside?

import java.util.Scanner;

public class Stops {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Start");
        int age = input.nextInt();
        System.out.println("Age: " + age);
        System.out.println("End");
    }
}
Show the output
Output
Start

Why? The exception stops the program at the line where it happened, so the lines after it never run. And abc does not become zero: no value was ever stored in age.

MethodUser typesResult
nextInt()abcInputMismatchException
nextInt()19.5InputMismatchException
nextDouble()abcInputMismatchException
nextDouble()1919.0
nextBoolean()yesInputMismatchException
next()19The string "19"

The user typed 19 for nextDouble. What does the program print?

import java.util.Scanner;

public class WholeInDouble {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double value = input.nextDouble();
        System.out.println(value);
    }
}
Show the output
Output
19.0

Why? Every whole number is also a valid decimal, so nextDouble accepts it. The reverse fails: 19.5 is not a whole number, so nextInt rejects it.

Part three: full programs

A calculator: two inputs and four operations

  1. InputRead two double numbers with a prompt for each.
  2. ProcessingCalculate the sum, difference, product and quotient.
  3. OutputPrint each result on its own line, with text that explains it.

Your calculator

Try 7 and 2. Then try 5 and 0: notice the result Infinity for the division. Then hand the calculator to a classmate and ask them to test it.

import java.util.Scanner;

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

        System.out.print("First number: ");
        double a = input.nextDouble();
        System.out.print("Second number: ");
        double b = input.nextDouble();

        System.out.println(a + " + " + b + " = " + (a + b));
        System.out.println(a + " - " + b + " = " + (a - b));
        System.out.println(a + " * " + b + " = " + (a * b));
        System.out.println(a + " / " + b + " = " + (a / b));
    }
}

The input: 7 then 2. Notice the parentheses around the sum. What does the program print?

import java.util.Scanner;

public class Sum {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double a = input.nextDouble();
        double b = input.nextDouble();
        System.out.println("Sum: " + a + b);
        System.out.println("Sum: " + (a + b));
    }
}
Show the output
Output
Sum: 7.02.0
Sum: 9.0

Why? This is the trap from the variables lecture, and it matters more now that the values come from the user. Without parentheses the numbers are stuck onto the text; with them they are added first.

Rectangle area: start by asking what the inputs are

QuestionAnswer
What are the inputs?Width and height, possibly with a fraction
What is the processing?width * height, 2 * (width + height)
What is the output?The area and the perimeter

Rectangle area and perimeter

Print the prompt Width: and read a decimal number, then the prompt Height: and read a decimal number. Then print Area: followed by the area on one line, and Perimeter: followed by the perimeter on the next.

import java.util.Scanner;

public class Rectangle {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the width and height, calculate, then print

    }
}
stdin
3
4
Expected output
Width: Height: Area: 12.0
Perimeter: 14.0
Hint 1

Use nextDouble for both values, even if a whole number is typed.

Hint 2

The perimeter needs parentheses: 2 * (width + height).

Solution
import java.util.Scanner;

public class Rectangle {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Width: ");
        double width = input.nextDouble();
        System.out.print("Height: ");
        double height = input.nextDouble();
        double area = width * height;
        double perimeter = 2 * (width + height);
        System.out.println("Area: " + area);
        System.out.println("Perimeter: " + perimeter);
    }
}

Temperature conversion: one formula for any value the user types

The formula: F = C * 9 / 5 + 32. We use printf to show one decimal place, as we learned last lecture.

Celsius to Fahrenheit

Try 37, 100 and -40. What is odd about the last one?

import java.util.Scanner;

public class Temperature {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Celsius: ");
        double celsius = input.nextDouble();
        double fahrenheit = celsius * 9 / 5 + 32;
        System.out.printf("%.1f C = %.1f F%n", celsius, fahrenheit);
    }
}

The input is 25. What does the program print?

import java.util.Scanner;

public class Weather {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Celsius: ");
        double celsius = input.nextDouble();
        System.out.printf("%.1f F%n", celsius * 9 / 5 + 32);
    }
}
Show the output
Output
Celsius: 77.0 F

Why? print keeps the prompt on the same line, and automatic input does not appear in the output. The calculation is 25 × 9 = 225, then ÷ 5 = 45, then + 32 = 77.

Fahrenheit to Celsius

Print the prompt Fahrenheit: and read a decimal number, convert it with the formula C = (F - 32) * 5 / 9, and print the result as 212.0 F = 100.0 C, with one decimal place for each value.

import java.util.Scanner;

public class ToCelsius {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the temperature, convert it, then print with printf

    }
}
stdin
212
Expected output
Fahrenheit: 212.0 F = 100.0 C
Hint 1

Do not forget the parentheses around F - 32.

Hint 2

Use the template "%.1f F = %.1f C%n".

Solution
import java.util.Scanner;

public class ToCelsius {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Fahrenheit: ");
        double fahrenheit = input.nextDouble();
        double celsius = (fahrenheit - 32) * 5 / 9;
        System.out.printf("%.1f F = %.1f C%n", fahrenheit, celsius);
    }
}

Final exercise: a student card from the keyboard

In the variables lecture we wrote the values of this card inside the code. Today the user types them, so one program works for every student at the university.

Student card

Read in order: Age: a whole number, then Name: a whole line, then GPA: a decimal number, then Grade: one character. Then print Sara Ali, age 19 on one line and GPA 3.75, grade A on the next, with two decimal places for the GPA.

import java.util.Scanner;

public class StudentCardInput {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read age, name, GPA and grade, then print the card

    }
}
stdin
19
Sara Ali
3.75
A
Expected output
Age: Name: GPA: Grade: Sara Ali, age 19
GPA 3.75, grade A
Hint 1

The name comes after nextInt: remember the trap?

Hint 2

Read the character with input.next().charAt(0).

Hint 3

Use printf with %.2f for the GPA and %c for the character.

Solution
import java.util.Scanner;

public class StudentCardInput {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        input.nextLine();
        System.out.print("Name: ");
        String name = input.nextLine();
        System.out.print("GPA: ");
        double gpa = input.nextDouble();
        System.out.print("Grade: ");
        char grade = input.next().charAt(0);
        System.out.println(name + ", age " + age);
        System.out.printf("GPA %.2f, grade %c%n", gpa, grade);
    }
}

Review questions

What does cannot find symbol mean on the line that has Scanner?

When does InputMismatchException appear?

Why do we usually use print, not println, for a prompt?

The input: 3.5 then Sara. What does the program print?

import java.util.Scanner;

public class ReviewTrap {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double gpa = input.nextDouble();
        String name = input.nextLine();
        System.out.println("[" + name + "] " + gpa);
    }
}
Show the output
Output
[] 3.5

Why? The trap is not unique to nextInt. Every method that reads a value but not the whole line leaves the Enter behind, and nextDouble is one of them.