2
import java.util.*;

class OverdueChecker {
    private static enum Response {YES, NO};
    private static final String DATE_SEPARATOR = "/";
    private Scanner scanner;
    private BookTracker bookTracker;

    //---------------------
    //     Constructor
    //---------------------
    public OverdueChecker() {
        scanner = new Scanner(System.in);
        scanner.useDelimiter("\\n");
        bookTracker = new BookTracker();
    }

    //-----------------
    //  Main Method
    //-----------------
    public static void main(String[] args) {
        OverdueChecker checker = new OverdueChecker();
        checker.start();
    }

    //-------------------------
    //      Public Method
    //-------------------------
    public void start() {
        GregorianCalendar returnDate;
        String table;
        double charge;
        Response response;

        inputBooks();

        table = bookTracker.getList();
        System.out.println(table);
        System.out.print("\nNow check the over due charges...\n");

        //try different return dates
        do {
            //read return date
            returnDate = readDate("\nReturn Date: ");
            charge = bookTracker.getCharge(returnDate);
            displayTotalCharge(charge);
            response = prompt("\nRun Again (yes/no)? ");
        } while (response == Response.YES);

        System.out.println("\n\nThank you for using Library Overdue Checker");
    }

    //----------------------------
    //      Private Method
    //-----------------------------
    private LibraryBook createBook(String title, double chargePerDay, double maxCharge, GregorianCalendar dueDate) {
        if(dueDate == null) {
            dueDate = new GregorianCalendar();      //set today as due date
        }

        LibraryBook book = new LibraryBook(dueDate);

        if(title.length() > 0) {
            book.setTitle(title);
        }
        if(chargePerDay > 0.0) {
            book.setChargePerDay(chargePerDay);
        }
        if (maxCharge > 0.0) {
            book.setMaximumCharge(maxCharge);
        }
        return book;
    }

    private void display(String text) {
        System.out.print(text);
    }

    private void displayTotalCharge(double charge) {
        System.out.format("\nTOTAL CHARGE:\t $%8.2f", charge);
    }

    private void inputBooks() {
        double chargePerDay, maxCharge;
        String title;

        GregorianCalendar dueDate;
        LibraryBook book;

        //Keeps on reading input from a console
        //until stopped by the end user
        while(!isContinue()) {
            System.out.println("\n");

            title        = readString("Title          : ");
            chargePerDay = readDouble("Charge per day : ");
            maxCharge    = readDouble("Maximum charge : ");
            dueDate      = readDate  ("Due date       : ");

            book = createBook(title, chargePerDay, maxCharge, dueDate);
            bookTracker.add(book);
        }
    }

    private boolean isContinue() {
        Response response = prompt("\nMore books to enter (y/n) ? ");
        return(response == Response.YES);
    }

    private Response prompt(String question) {
        String input;
        Response response = Response.NO;
        System.out.print(question + "(Yes - y; No - n) : ");
        input = scanner.next();

        if(input.equals("Y") || input.equals("y")) {
            response = Response.YES;
        }

        return response;
    }

    private double readDouble(String prompt) {
        display(prompt);
        return scanner.nextDouble();
    }

    private GregorianCalendar readDate(String prompt) {
        GregorianCalendar cal;

        String yearStr, monthStr, dayStr, line;
        int sep1, sep2;

        display(prompt);
        line = scanner.next();

        if(line.length() == 0) {
            cal = null;
        } else {
            sep1 = line.indexOf(DATE_SEPARATOR);
            sep2 = line.lastIndexOf(DATE_SEPARATOR);

            monthStr = line.substring(0, sep1);
            dayStr = line.substring(sep1 + 1, sep2);
            yearStr = line.substring(sep2 + 1, line.length());

            cal = new GregorianCalendar(Integer.parseInt(yearStr), Integer.parseInt(monthStr)-1, Integer.parseInt(dayStr));
        }

        return cal;
    }

    private String readString(String prompt) {
        display(prompt);
        return scanner.next();
    }

 }

I was tried to compile the library overdue checker program that I followed from a book but ended with this error.

Title          : jkj
    Charge per day : 9
    Exception in thread "main" java.util.InputMismatchException
            at java.base/java.util.Scanner.throwFor(Scanner.java:939)
            at java.base/java.util.Scanner.next(Scanner.java:1594)
            at java.base/java.util.Scanner.nextDouble(Scanner.java:2564)
            at OverdueChecker.readDouble(OverdueChecker.java:130)
            at OverdueChecker.inputBooks(OverdueChecker.java:101)
            at OverdueChecker.start(OverdueChecker.java:40)
            at OverdueChecker.main(OverdueChecker.java:28) 

Actually, the program will ask the user the details of the book that overdue return (title, charge per day, due date, return date) and will compute the total charge

Oddly, when my friends run it on their laptop it does work. Can anyone give me a solution?

Anggi3si
  • 23
  • 2
  • It may be due to the previous input, typing a `String` and hitting enter will return the `String` but keep the "line break (\n)" inside the buffer, can you try to input a `String` using `nextLine()` instead of `next()`? – adxl Mar 21 '20 at 13:25

2 Answers2

0

Change the Scanner.nextDouble() in readDouble() to read a String using Scanner.next() instead and output it with System.out.println(). You'll probably see that you're reading something else due to the wrong setup of a delimiter in your Scanner.

This is not the specific problem answer, rather a general technique for debugging input parsing here.

s.fuhrm
  • 408
  • 2
  • 7
0

1. Change the definition of readDouble as follows:

private double readDouble(String prompt) {
    boolean valid;
    double d = 0;
    do {
        valid = true;
        display(prompt);
        try {
            d = Double.parseDouble(scanner.nextLine());
        } catch (NumberFormatException | NullPointerException e) {
            System.out.println("Invalid input. Try again");
            valid = false;
        }
    } while (!valid);
    return d;
}

2. Change all occurrences of scanner.next(); to Scanner.nextLine();

Check Scanner is skipping nextLine() after using next() or nextFoo()? for more information.

Arvind Kumar Avinash
  • 50,121
  • 5
  • 26
  • 72