Simple calculate using inheritance and Scanner how i handle these Exceptions? - java

I'm trying to make a simple calculator using scanner and inheritance too, after i insert two numbers and operator i found this Exception
the Exception is :
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextShort(Scanner.java:1987)
at java.util.Scanner.nextShort(Scanner.java:1946)
at calculator.simplecalc.<init>(simplecalc.java:18)
at calculator.simplecalc_inhe.<init>(simplecalc_inhe.java:7)
at calculator.Calculator.main(Calculator.java:6)
My Java Code: first class is Superclass it name is simplecalc.java
package calculator;
import java.util.Scanner;
public class simplecalc {
private int val1;
private int val2;
private Scanner sca;
public char op;
public int result;
public simplecalc ()
{
sca = new Scanner(System.in);
System.out.println("Enter the first number");
val1 = sca.nextInt();
System.out.println("Enter the Second number");
val2 = sca.nextInt();
System.out.println("choose an operator + or - or * or / ");
op = (char) sca.nextShort();
System.out.println(op);
}
/*use if operator not equal + or - */
public char set_op()
{
op = (char) sca.nextShort();
return op;
}
public int calsum()
{
return this.val1 + this.val2;
}
public int calsub()
{
return this.val1 - this.val2;
}
//i don't use setX and setX i write them because i use getX,Y
/* public void setX(int x)
{
this.val1 = x;
}
public void setY(int y)
{
this.val2 = y;
} */
public int getX()
{
return this.val1;
}
public int getY()
{
return this.val2;
}
}
Subclass: simplecalc_inhe.java
package calculator;
public class simplecalc_inhe extends simplecalc {
public simplecalc_inhe()
{
super();
}
public int mult()
{
return this.getX() * this.getY();
}
public int div()
{
int z = this.getY();
if(z == 0){
return 0;
}
return this.getX() / z;
}
}
Main-class: Calculator.java
package calculator;
public class Calculator {
public static void main(String[] args) {
simplecalc_inhe cal = new simplecalc_inhe();
if (cal.op != '+' || cal.op != '-' || cal.op != '*' || cal.op != '/' )
{
System.out.println("You must enter a vaild operator");
cal.set_op(); //to set operator
} else {
if(cal.op == '+' ) {
cal.result = cal.calsum();
System.out.println(cal.result);
}else if(cal.op == '-') {
cal.result = cal.calsub();
System.out.println(cal.result);
}else if(cal.op == '*') {
cal.result = cal.mult();
System.out.println(cal.result);
}else if(cal.op == '/') {
cal.result = cal.div();
System.out.println(cal.result);
}
}
}
}
I hope i explained that error well with most of details, Thank You.

From the Java doc itself :
public short nextShort() : Scans the next token of the input as a short.
Throws:
InputMismatchException - if the next token does not match the Integer
regular expression, or is out of range
Because +/-* does not match as an Integer
Ypu maye use op = sca.nextLine().charAt(0);
And also, to use the return line properly, better do :
val1 = Integer.parseInt(sca.nextLine());
val2 = Integer.parseInt(sca.nextLine());
op = sca.nextLine().charAt(0);
Also your test if not good, because if you enter a '-', it will be different of '+' so true and you'll og into the if, in fact you need to og inot if it's different of ALL 4 possib, fix by :
if (cal.op != '+' && cal.op != '-' && cal.op != '*' && cal.op != '/' )
To ask the user until he give a good operator you can do like this : (but it will also ask again the 2 ints because it's the same method) / to avoid same code better put the print at the end, and use a switch, it's more performant :
do{
System.out.println("You must enter a vaild operator");
cal.set_op(); //to set operator
} while(cal.op != '+' && cal.op != '-' && cal.op != '*' && cal.op != '/' );
switch(cal.op){
case '+':
cal.result = cal.calsum();
break;
case '-':
cal.result = cal.calsub();
break;
case '*':
cal.result = cal.mult();
break;
case '/':
cal.result = cal.div();
break;
default : break; //safety check
}
System.out.println(cal.result); //try to not have SAME code written twice (or more^^)

There is your problem:
System.out.println("choose an operator + or - or * or / ");
op = (char) sca.nextShort();
Neither + nor - nor * nor / can be read with nextShort.
You can use
public String next(Pattern pattern)
Returns the next token if it matches the specified pattern. This
method may block while waiting for input to scan, even if a previous
invocation of hasNext(Pattern) returned true. If the match is
successful, the scanner advances past the input that matched the
pattern.
link

Firstly the Scanner designed to retrieve the line of values separated by white space characters. So if you want to read a character then use
op = (char)System.in.read()
this above line will fetch you the character you entered so that you need not bother about IndexOutofBoundException because you are not doing a get from index and no NullPointerException because you are playing with variables than objects.
So now looking at your code it is clear that you are writing a method which accepts the character and does the operation so in that case you can just simply create a switch case and check all possible operations by case and throw error message from default case
so refactoring your code as
public void doOperation() {
switch(cal.op)
{
case '+' :
cal.result = cal.calsum();
System.out.println(cal.result);
break;
case '-' :
cal.result = cal.calsub();
System.out.println(cal.result);
break;
case '*' :
cal.result = cal.mult();
System.out.println(cal.result);
break;
case '/' :
cal.result = cal.div();
System.out.println(cal.result);
break;
default : System.out.println("You must enter a vaild operator");
cal.set_op();
doOperation();
}
}

Related

Make program quit based on user input

I want my program to quit when I input "Q" or "q". However, the loop never finishes. Can you help me figure it out, please?
public static void main(String[] args) {
Scanner input= new Scanner(System.in);
char str ;
do {
System.out.println("Choose one of the following option : ");
System.out.println("U or u - to convert SAR amount to USD");
System.out.println("E or e - to convert SAR amount to EURO");
System.out.println("Q or q - to quit");
str = input.next().charAt(0);
if (str == 'U' || str == 'u' ) {
}
else if (str == 'E' || str == 'e' ){
}
} while( str != 'Q' || str != 'q' );
}
str != 'Q' || str != 'q' is always true. Any given string is not equal to one or the other of these (or both). You want && instead of ||.
A nice structure to use would be the structure similar to the one recommended for getopt_long() in C but for Java obviously. Can read the man page here https://linux.die.net/man/3/getopt_long
while(true)
{
str = input.next().charAt(0);
if(str.toUpperString.equals('Q'))
{
break;
}
// In general if you want upper and lower case to do the same thing
//use toUpperString
switch (str) {
case 'U':
case 'u':
// Do something
break;
case 'E':
case 'e':
// Do something
break;
default:
System.out.println("Wrong input");
break;
}
}
Another good solution to this problem, if you don't want to use the switch statement, is the loop-and-a-half.
https://codehs.gitbooks.io/introcs/content/Basic-JavaScript-and-Graphics/loop-and-a-half.html
The structure goes like this:
while(true)
{
String token = Character.toUpperCase( input.next().charAt(0) );
if(token.equals('A'))
{
// Do something
}
else if(token.equals('B'))
{
// Do something
}
else if(token.equals('Q'))
{
break;
}
else
{
System.out.println("Invalid Option");
}
}
If you want to stop the program when you write Q or q. you can convert the input to any of the lower or uppercase.
str.toUpperCase();
if (str == 'U'){
}
else if (str == 'E'){
}
} while( str != 'Q');
}
OR
change the condition for checking Q or q.
while( str != 'Q' && str != 'q' );
for the above code snippet, the while loop will execute if str is not Q or q.
public static void main(String [] args) {
Scanner input= new Scanner(System.in);
char str ;
do{
System.out.println("Choose one of the following option : ");
System.out.println("U or u - to convert SAR amount to USD");
System.out.println("E or e - to convert SAR amount to EURO");
System.out.println("Q or q - to quit");
str = input.next().charAt(0);
if (str == 'U' || str == 'u'){}
else if (str == 'E' || str == 'e'){}
} while(str != 'Q' && str != 'q'); // change the condition from || to &&
// Also close the input stream to avoided memery leakage
input.close();
}

Requiring user to enter only 1 char for a letter grade for a gpa program

I am trying to finish up this Java assignment and I am stuck on this last bit. I need to make it so when a user enters a letter grade in order to calculate their G.P.A. they can only enter one letter.
For example, they need to receive an error if they enter aaa instead of a.
I am stuck on how to go about doing this. Everything works except this one thing. I am very new to Java so any help would be great.
Here is my class:
public class Gpa {
private int sumCredits;
private int sumPoints;
public int getPointsForGrade(char letter) {
int gradepoints;
switch (letter)
{
case 'A':
case 'a':
gradepoints = 4;
break;
case 'B':
case 'b':
gradepoints = 3;
break;
case 'C':
case 'c':
gradepoints = 2;
break;
case 'D':
case 'd':
gradepoints = 1;
break;
case 'F':
case 'f':
gradepoints = 0;
break;
default:
gradepoints = -1;
break;
}
return gradepoints;
}
public void Constructor(){
sumCredits = 0;
sumPoints = 0;
return;
}
public void addGrade( char letter, int credits){
sumCredits = sumCredits + credits;
sumPoints = sumPoints + getPointsForGrade(letter) * credits;
}
public double calcGPA(){
double GPA;
if (sumCredits == 0){
return 0;
}
GPA = (double)sumPoints / sumCredits;
return GPA;
}
public int totalCredits(){
return sumCredits;
}
public int totalPoints(){
return sumPoints;
}
}
and here is my test class, or gpa calculator
import java.util.*;
import java.util.Scanner;
public class ComputeGpa {
public static void main (String [] args){
Scanner scan = new Scanner(System.in);
Gpa gpa = new Gpa();
int courses;
int credits;
char letter;
while (true){
System.out.println(" Enter number of courses: ");
courses = scan.nextInt();
if (courses > 0){
break;
}
else {
System.out.println(" Invalid number of courses - must be greater than 0");
}
}
for (int i = 1; i<= courses; i++)
{
while (true){
System.out.println(" Enter Grade ( one character )");
String grade = scan.next();
letter = grade.toUpperCase().charAt(0);
if (letter == 'A' || letter == 'B' || letter == 'C' || letter =='D' || letter == 'F' ){
break;
}
else {
System.out.println(" must enter A,B,C,D,F (Upper or Lower case)");
}
if (letter != 'A' || letter != 'B' || letter != 'C' || letter != 'D' || letter != 'F'){
System.out.println("must be 1 letter only");
}
}
while (true){
System.out.println(" Enter Credits: ");
credits = scan.nextInt();
if (credits < 0 || credits > 9){
System.out.println("Invalid credits = must be between 0 and 9, inclusively");
}
else {
break;
}
}
gpa.addGrade(letter, credits);
System.out.println(" Points: " + gpa.getPointsForGrade(letter) );
System.out.println(" Sum Points: " + gpa.totalPoints() + " Sum Credits: " + gpa.totalCredits());
}
System.out.printf(" GPA: %.2f%n", gpa.calcGPA());
}
}
You could just check to see if there are more entries in the input. I did not run this code, but this is a simple way to check.
System.out.println(" Enter Grade ( one character )");
String grade = scan.next();
letter = grade.toUpperCase().charAt(0);
if(grade.length() > 1){ // check the size of the input
System.out.println("You entered too many letters");
}
else if (letter == 'A' || letter == 'B' || letter == 'C' || letter =='D' || letter == 'F' ){
break;
}
else {
System.out.println(" must enter A,B,C,D,F (Upper or Lower case)");
}
Where you ran scan.next() and stored it into a string, you can check the length of the string.
if (grade.length() > 1) {
// show an error or throw an exception or smth
System.out.println("Error, too many chars"); // do this if you want to print an error
throw new Exception("TOO MANY CHARS"); // do this and don't catch it if you want to crash the program
}
EDIT: For OP's request of asking for the grade again if it's wrong
String grade = "x"; // set the base case that will never occur
while (!grade.equals("x")) { // check if it is x - if it's not x, continue
if ((grade = scan.next()).length() == 1) {
// check the length - if it's 1 letter
// check the letter here. If it's not a valid letter,
// set grade back to x
} else {
// if you're here, it wasn't 1 letter.
// print an error msg
System.out.println("too many chars");
// Therefore, set grade back to x so that we ask again
grade = "x";
}
}

Is there a more efficient way to check characters in a string?

For this assignment, I need to accept a lock combination and check if:
It is 9 chars long
At position 2,8 the char is R or r
At position 5 the char is l or L
All of the other positions are integers 0-9
I am wondering if there is a better way to do this than checking each position for a digit?
Scanner input = new Scanner(System.in);
String lockComb;
System.out.print("Please enter a lock combination ( ddRddLddR ): ");
lockComb = input.nextLine();
if((lockComb.length() == 9) && ((lockComb.charAt(2) == 'r') || (lockComb.charAt(2) == 'R')) &&
((lockComb.charAt(5) == 'l') || (lockComb.charAt(5) == 'L')) && ((lockComb.charAt(8) == 'r')
|| (lockComb.charAt(8) == 'R')))
{
if((Character.isDigit(lockComb.charAt(0))) && (Character.isDigit(lockComb.charAt(1))) &&
(Character.isDigit(lockComb.charAt(3)) && (Character.isDigit(lockComb.charAt(4))) &&
(Character.isDigit(lockComb.charAt(6))) && (Character.isDigit(lockComb.charAt(7)))))
{
System.out.println(lockComb + " is a valid lock combination!");
}
else
{
System.out.println(lockComb + " is not a valid lock combination!");
}
}
else
{
System.out.println(lockComb + " is not a valid lock combination!");
}
To simplify things, you can use a regular expression:
if (lockComb.matches("[0-9][0-9][rR][0-9][0-9][lL][0-9][0-9][rR]")
(That's lowercase-l and uppercase-L in the middle.)
(No need to check the length, which is implicitly defined by the regular expression.)
How about just for fun a solution that doesn't involve regular expressions. I'm not arguing at all for or against just merely a different solution. One thing you do lose if using a regular expression is the ability to tell exactly why this is not a valid lock combination. It's up to you to figure out what the best solution is given the scenario you are coding for.
public static boolean matcher (String lockComb) {
if(lockComb.length() != 9) {
System.out.println(lockComb + " is not a valid lock combination!");
return false;
}
boolean isValid = true;
char[] comb = lockComb.toUpperCase().toCharArray();
for (int i = 0; i < comb.length; i++) {
switch (i) {
case 2:
case 8:
isValid = (comb[i] == 'R');
break;
case 5:
isValid = (comb[i] == 'L');
break;
default:
isValid = Character.isDigit(comb[i]);
break;
}
if(isValid == false) break;
}
if(isValid) {
System.out.println(lockComb + " is a valid lock combination!");
} else {
System.out.println(lockComb + " is not a valid lock combination!");
}
return isValid;
}

Java issue with scanner

I have a method that should scan for one of 3 letters in caps or lowercase and return the lower case version of the letter. If an improper letter is entered the user is warned and reasked for a letter. I have two issues, 1: as soon as the method is run I get the outputted line with the error message telling the user invalid entry without waiting for an entry! (so the second the method is run I see High, low or sevens (H/L/S):Invalid entry. Please try again using H/L/S! before entering anything then the method is recalled again and all works fine form there except for my next issue) 2: the entry that is gotten from the scanner never passes any of my if statements even though it should.
my code:
private static char getHighLow(Scanner inScanner) {
System.out.print("High, low or sevens (H/L/S):");
String entered = inScanner.nextLine();
System.out.print(entered);
if(entered.equals("H") || entered.equals("h")){
return 'h';
}
else if (entered.equals("L") || entered.equals("l")){
return 'l';
}
else if(entered.equals("S") || entered.equals("s")){
return 's';
}
char result = 0;
while(result != 'l' || result != 'h' || result != 's'){
System.out.println("Invalid entry. Please try again using H/L/S!");
result=getHighLow(inScanner);
}
return result;
}
Instead of using while(), you can use 'else' like this-
private static char getHighLow(Scanner inScanner) {
System.out.print("High, low or sevens (H/L/S):");
String entered = inScanner.nextLine();
System.out.print(entered);
if(entered.equals("H") || entered.equals("h")){
return 'h';
}
else if (entered.equals("L") || entered.equals("l")){
return 'l';
}
else if(entered.equals("S") || entered.equals("s")){
return 's';
}
else {
System.out.println("Invalid entry. Please try again using H/L/S!");
return getHighLow(inScanner);
}
}
You can simply use equalsIgnoreCase and trim the entered string. And add a while loop util your condition is satisfied.
Scanner scanner = new Scanner(System.in);
boolean loop = true;
String choice = null;
while (loop) {
System.out.print("High, low or sevens (H/L/S):");
choice = scanner.nextLine();
if ("H".equalsIgnoreCase(choice.trim())
|| "L".equalsIgnoreCase(choice.trim())
|| "S".equalsIgnoreCase(choice.trim())) {
System.out.println("Correct Choice");
loop = false;
}
else
{
System.out.println("Wrong Choice");
}
}
System.out.print(choice);
char result;
while(true){
System.out.print("High, low or sevens (H/L/S):");
String entered = inScanner.nextLine();
System.out.print(entered);
if(entered.equals("H") || entered.equals("h")){
result = 'h';break;
}
else if (entered.equals("L") || entered.equals("l")){
result = 'l';break;
}
else if(entered.equals("S") || entered.equals("s")){
result = 's';break;
}else{
System.out.println("Invalid entry. Please try again using H/L/S!");
}
}
Hey you are not breaking out of the while loop at all. Did you see that ?
This is what you want. Here is the program to iterate over characters in a String. And convert them in lower case letter if they are H,L OR S.
package testproj;
import java.util.Scanner;
public class TestProj {
public static void main(String[] args) {
Scanner scanner = new Scanner("HLs");
String result = getHighLow(scanner);
System.out.println("Result :"+result);
}
private static String getHighLow(Scanner inScanner) {
System.out.println("High, low or sevens (H/L/S):");
String entered;
String result = "";
boolean isCharFound = false;
String temp = "";
while (inScanner.hasNext()) {
temp = inScanner.next();
System.out.println(temp);
for (int index = 0; index < temp.length(); index++) {
entered =new Character(temp.charAt(index)).toString() ;
if (entered.equals("H") || entered.equals("h")) {
result = result + 'h';
isCharFound = true;
} else if (entered.equals("L") || entered.equals("l")) {
result = result + 'l';
isCharFound = true;
} else if (entered.equals("S") || entered.equals("s")) {
result = result + 's';
isCharFound = true;
}
if (!isCharFound) {
System.out.println("Invalid entry. Please try again using H/L/S!");
}
isCharFound = false;
}
}
return result;
}
}

Stack Calculator: Trouble evaluating postfix expression because of casting issue

I'm working on a homework assignment that asks me to create a calculator that changes the expression given to it from infix to postfix to then evaluate. I must do so using stacks but may choose any stack implementation I want as long as I don't use the java.util.Stack from the JCF. I chose a referenced based stack.
The problem I'm having is in my evaluatePostfix method. In order to evaluate the expression I had to cast my operand variables as Integers but eclipse doesn't seem to like that. I keep getting a "java.lang.Character cannot be cast to java.lang.Integer" error. I'm not sure how to fix this issue. Does anyone have any insight?
Here is my code:
public class InfixToPostfixAndEvaluateCalculator {
private String infix;
private String postfix;
private int result;
public InfixToPostfixAndEvaluateCalculator() {
infix=null;
postfix=null;
result=0;
}
public InfixToPostfixAndEvaluateCalculator(String infix) {
this.infix=infix;
postfix=null;
result=0;
}
public String getInfix() {
return infix;
}
public String getPostfix() {
return postfix;
}
public int getresult() {
return result;
}
public void setInfix(String infix) {
this.infix=infix;
}
public void setPostfix(String postfix) {
this.postfix=postfix;
}
public String toString() {
return " Infix: "+infix+"\n Postfix: "+postfix+"\n Result: "+result+"\n";
}
public String infixToPostfix() { //Carrano 2nd ed. p.354
//opStack is a stack of Character objects, such as '+','-','*','/', and ')'
StackInterface opStack=new StackReferenceBased();
String postfixExp=""; //the expression to be built in this method
//for each character ch in the string infix
for (int i=0; i<infix.length(); i++) {
char ch=infix.charAt(i);
switch (ch) {
//if ch is an operator
case '+': case '-': case '*': case '/':
while ( (!opStack.isEmpty())
&& (!opStack.peek().equals('('))
&& (precedence(ch) <= precedence((Character)opStack.peek()))){
postfixExp = postfixExp + opStack.pop();
}
opStack.push(ch);
break;
case '(': //add to stack
opStack.push(ch);
break;
case ')': //start popping things off the stack until you find opening parenthesis, use peak
while (!((Character)opStack.peek()).equals('(')){
postfixExp = postfixExp + opStack.pop();
}//end while
opStack.pop();
break;
default: //ch is an operand
postfixExp = postfixExp + ch;
break;
}//end of switch
}//end of for
System.out.println("End of for loop.");
//append to postfixExp the operators remaining in the stack
while (! opStack.isEmpty()) {
postfixExp=postfixExp+((Character) opStack.pop()).charValue();
}//end of while
postfix=postfixExp; //update the instance variable
return postfixExp;
}//end of infixToPostfix()
//little helper function to determine precedence value of an operator
// *,/ have value of, say 20
// +,- have value of, say 10
private int precedence(char ch) {
int prec = 20;
int prec2 = 10;
if (ch == '*' || ch == '/'){
return prec;
}
if (ch == '+' || ch == '-'){
return prec2;
}
return -1;
}
public int evaluatePostfix() { //Carrano 2nd ed. pp.350-351
//valueStack is a stack of Integer objects:
StackInterface valueStack=new StackReferenceBased();
//variables for the operands:
int operand1, operand2;
//for each character ch in the string postfix
for (int i=0; i<postfix.length(); i++) {
char ch=postfix.charAt(i);
switch (ch) {
//if ch is an operator
case '+':
operand2 = (Integer)valueStack.pop();
operand1 = (Integer)valueStack.pop();
result = operand1 + operand2;
valueStack.push(result);
break;
case '-':
operand2 = (Integer)valueStack.pop();
operand1 = (Integer)valueStack.pop();
result = operand1 - operand2;
valueStack.push(result);
break;
case '*':
operand2 = (Integer)valueStack.pop();
operand1 = (Integer)valueStack.pop();
result = operand1 * operand2;
valueStack.push(result);
break;
case '/':
operand2 = (Integer)valueStack.pop();
operand1 = (Integer)valueStack.pop();
result = operand1 / operand2;
valueStack.push(result);
break;
default: //ch is an operand
valueStack.push(ch);
break;
}//end of switch
}//end of for
//at the end, the value of the expression will be on the top of the stack
result=((Integer) valueStack.pop()).intValue();
return result;
}//end of evaluatePostfix()
} // end StackTest
Yes, you cannot cast Character to Integer.
To do that you can use,
Integer.parseInt(String.valueOf(valueStack.pop()));
parseInt doesn't take Character as argument so, you have to convert first into String and then to Integer.
there is a function to get the numeric int value of a Unicode character
Character.getNumericValue( ch );
hopefully the StackInterface supports type-information
this would prevent dozens of (Integer)-casts
StackInterface<Integer> valueStack = new StackReferenceBased<Integer>();

Categories

Resources