Java Calculator issue using try/catch and system.in.read();

korismith

New Coder
Dec 13, 2019
2
0
1
I have run into some issues. I am being required to build a calculator, and for some reason, when I try using my "while (answer == 'Y')" statement, when I do the rest of the calculator such as inputting the numbers and the operation, it tells me the answer, outputs the message asking to try again, and then automatically takes the fact that I gave the answer variable the 'y' char already, and just immediately ends the program without letting me input y or n...


Java:
package homework3calculator;
public class Homework3Calculator {
    public static int readNumber() throws Exception {
        int digitAsciiCode = 0;
        int digitNumericValue = 0;
        int number = 0;
            
        while (digitAsciiCode != '\n') {
            digitAsciiCode = System.in.read();
            
            if ( digitAsciiCode != '\n') {
                digitNumericValue = digitAsciiCode - '0';
                number = number * 10 + digitNumericValue;
            }
        } return number;
    }
    public static void main(String[] args) {
        int number1 = 0;
        int number2 = 0;
        char operation;
        double result = 0.0;
        char answer = 'Y';
        
        try {
            while (answer == 'Y') {
                System.out.println("Enter the first number.");
                number1 = readNumber();
                System.out.println("Enter the second number.");
                number2 = readNumber();
                System.out.println("Please enter an operation.");
                operation = (char)System.in.read();
            
                if (operation == '+') {
                    result = number1 + number2;
                } if (operation == '-') {
                    result = number1 - number2;
                } if (operation == '*') {
                    result = number1 * number2;
                } if (operation == '/') {
                    if (number2 == 0)
                        System.out.println("Cannot divide by 0.");
                    else {
                        result = number1 / number2;
                    }
                }
                System.out.println("The result is: " + result);
                System.out.println("Would you like to try again? (Y/N)");
                answer = (char)System.in.read();
            }
        }
        catch (Exception e) {
            System.out.println("Keyboard failed!");
        }
    }
}
 
Jun 26, 2019
72
19
8
I had a quick try to debug your code at repl.it link here but couldn't immediately find a solution. I tried looking into flushing the input stream before getting the user input for repeating, but that didn't work either.

I did a google search for flushing the input stream but it seems like the new way to manage user input from system input is to use the Scanner class - turned up StackOverflow link https://stackoverflow.com/questions/18273751/flush-clear-system-in-stdin-before-reading . I've seen the use of the Scanner class in various online test sites like HackerRank (I'm pretty sure that's where I first saw it) so see if that helps.
 

Cpl_Barcus

New Coder
Jan 13, 2020
3
2
2
Your block of if statements to return the result can be changed to a switch statement for readability and speed purposes. Switch statements utilize jump tables and since you are chars are valid inputs for switch statements. You can also utilize byte, short, int, Character, Byte, Short, Integer, String, or an enum types. Although the speed boost is negligible here, it's a good practice to get into the habit of using switch over nested ifs.

The code would look as follows:

Java:
switch(operation){
    case '+':
        result = number1 + number2;
    case '-':
        result = number1 - number2;
    case '*':
        result = number1 * number2;
    case '/':
        if (number2 == 0)
            System.out.println("Cannot divide by 0.");
        else {
            result = (double)number1 / number2;
        }

}
Next is a fatal flaw in your program. Try entering something like 5 / 7. The result is 0.0
This is easily fixed by casting number1 / number2 into a double.

Java:
result = (double)number1 / number2;
Next, if your user enters a number to divide by 0 we should also be using the continue keyword to restart the while loop as not to waste resources computing something that doesn't need to be computed also with the given benefit of not displaying a result since there is no 'result'.

Java:
if (number2 == 0) {
    System.out.println("Cannot divide by 0.");
    continue;

It is also best practice to utilize the Scanner class over System.in.read. Using the Scanner class also clears up your problem.

First, we need to initialize the new object with the Scanner class and import java.util.Scanner. To do this we import java.util.Scanner and then insert the initialization at the top of our Main function.

Java:
import java.util.Scanner;
Java:
Scanner scanner = new Scanner(System.in);
We then need to replace all of the readNumber() calls so our block of code starting the while loop will be

Java:
System.out.println("Enter the first number.");
// Read next integer from input
number1 = scanner.nextInt();

System.out.println("Enter the second number.");
// Read next integer from input
number2 = scanner.nextInt();

System.out.println("Please enter an operation.");
// Read next character from input
operation = scanner.next().charAt(0);
Finally, we need to not have your repeat always set to false.

Java:
repeat = false;
with

Java:
repeat = answer != 'n';
Or something similar.

The resulting code, with all the changes, will be this:

Java:
import java.util.Scanner;
public class Main {
    public static int readNumber() throws Exception {
        int digitAsciiCode = 0;
        int digitNumericValue = 0;
        int number = 0;
        while (digitAsciiCode != '\n') {
            digitAsciiCode = System.in.read();
            if ( digitAsciiCode != '\n') {
                digitNumericValue = digitAsciiCode - '0';
                number = number * 10 + digitNumericValue;
            }
        } return number;
    }
    public static void main(String[] args) {
        int number1 = 0;
        int number2 = 0;
        char operation;
        double result = 0.0;
        boolean repeat = true;
        char answer = ' ';
        Scanner scanner = new Scanner(System.in);
        try {
            while (repeat) {
                System.out.println("Enter the first number.");
                number1 = scanner.nextInt();
                System.out.println("Enter the second number.");
                number2 = scanner.nextInt();
                System.out.println("Please enter an operation.");
                operation = scanner.next().charAt(0);
                switch(operation){
                    case '+':
                        result = number1 + number2;
                    case '-':
                        result = number1 - number2;
                    case '*':
                        result = number1 * number2;
                    case '/':
                        if (number2 == 0) {
                            System.out.println("Cannot divide by 0.");
                            //continue;
                        }
                        else {
                            result = (double)number1 / number2;
                        }
                }
                System.out.println("The result is: " + result);
                System.out.println("Would you like to try again? (Y/N)");
                System.out.println("(answer: " + answer);
                answer = scanner.next().charAt(0);
                System.out.println("(read answer " + answer);
                repeat = answer != 'n' && answer != 'N';
            }
        }
        catch (Exception e) {
            System.out.println("Keyboard failed!");
        }
    }
}
 
  • Like
Reactions: Master Yoda