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>();
Related
this is my last resort. Will someone help me with my program?
The program is to convert infix to postfix, the issue is it won't give me an answer with decimal. I know i need to use double, but i don't know where to insert it.
here is my code
import java.util.*;
class Stack
{
int capacity = 10;
char arr []=new char[capacity];
int top = -1;
boolean isEmpty()
{
if(top==-1){
return true;
}
else {
return false;
}
}
void push(char c)
{
top++;
if (top <= capacity-1)
{
arr[top]= c;
}
else if (top > capacity-1)
{
System.out.println("Overflow"); //Stack is ful
System.exit(0);
}
}
char pop ()
{
if (isEmpty()==true){
System.out.print("Underflow");
System.exit(0);
}
return arr[top--];
}
char peek()
{
return arr[top];
}
}
public class Operations
{
static Stack s = new Stack ();
static int precedence(char c){
switch (c){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
}
return -1;
}
public static String Conversion(String val){
String result = "";
for (int i = 0; i <val.length() ; i++) {
char c = val.charAt(i);
if(precedence(c)>0){
while(s.isEmpty()==false && precedence(s.peek())>=precedence(c)){
result += s.pop();
}
s.push(c);
}else if(c==')'){
char x = s.pop();
while(x!='('){
result += x;
x = s.pop();
}
}else if(c=='('){
s.push(c);
}else{
result += c;
}
if (i+1 >= val.length() || !Character.isDigit(val.charAt(i+1)))
result += ' ';
}
while (!s.isEmpty())
result = result + s.pop();
return result;
}
public static double Result(String Postfix)
{
for(int i=0; i < Postfix.length(); i++)
{
char ch = Postfix.charAt(i);
//check if it is a space (separator)
if(ch==' ')
continue;
if (Character.isDigit(ch)){
double num = 0;
while(Character.isDigit(ch)) {
num = num*10 + (ch-'0');
i++;
ch = Postfix.charAt(i);
}
i--;
s.push((char)(num));
}
else
{
double value1 = s.pop();
double value2 = s.pop();
switch(ch) //evaluating the expression
{
case '+':
s.push((char)(value2 + value1));
break;
case '-':
s.push((char)(value2 - value1));
break;
case '*':
s.push((char)(value2*value1));
break;
case '/':
if(value1==0){
System.out.print("Cannot divide by zero");
System.exit(0);
}
else
s.push((char)(value2/value1));
break;
}
}
}
return s.pop();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter an infix expression: ");
String val = sc.next();
String Postfix = Conversion(val);
System.out.println("Postfix expression is: "+(Postfix.replaceAll("\\s+","")));
System.out.println("Result of the evaluation is: " + Result(Postfix));
}
}
i am not confident with the codes if it's correct. but any enlighten is welcome.
and perhaps can u help me with the loop? so i won't start to re-run the program everytime i input from the keyboard, big thanks seniors
I'm trying to make an infix to expression tree program for school in Java, to do so I am trying to implement a postfix queue which is constructed after being passed an infix String, inside of this queue I am using the Java Stack to hold onto operators and left parenthesis for the shunting-yard algorithm, the expression tree has to use generic nodes to hold char/int.
When my program tries to push the first '(' encountered, I am encountering a heap memory error
"Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOf(Arrays.java:3511)
at java.base/java.util.Arrays.copyOf(Arrays.java:3480)
at java.base/java.util.Vector.grow(Vector.java:262)
at java.base/java.util.Vector.grow(Vector.java:266)
at java.base/java.util.Vector.add(Vector.java:782)
at java.base/java.util.Vector.addElement(Vector.java:617)
at java.base/java.util.Stack.push(Stack.java:66)
at project01/project1.PostfixQueue.<init>(PostfixQueue.java:128)
at project01/project1.ExpressionTree.<init>(ExpressionTree.java:22)
at project01/project1.Driver.main(Driver.java:11)"
public PostfixQueue(String infix) {
Stack<Character> opStack = new Stack<Character>();
PostfixQueue postQueue = new PostfixQueue();
Character digit;
int numDigits = 0, result = 0;
while(infix.length() > 0) {
digit = (Character) infix.charAt(0);
switch(digit) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
if(numDigits > 0) {
result = (result * 10) + Character.getNumericValue(digit); //if a result int is previously stored (multi digit int in the string)
if(infix.charAt(1) >= 48 && infix.charAt(1) <= 57) {
numDigits++;
}
else {
//output result
postQueue.Enqueue(result);
numDigits = 0; //reset numDigits
}
}
else if(numDigits == 0) {
if(infix.charAt(1) >= 48 && infix.charAt(1) <= 57) { //If next input is a number w/o whitespace (ex: 45)
numDigits++;
result = Character.getNumericValue(digit);
}
else {
numDigits = 0; //reset numDigits
//output result
postQueue.Enqueue(result);
}
} //End else if
break;
case '+':
case '-':
if(opStack.empty() || opStack.peek() == '(')
{
opStack.push(digit);
}
else{
while(opStack.peek() == '+' || opStack.peek() == '-' || opStack.peek() == '*' || opStack.peek() == '/') {
//Pop operator and queue it
postQueue.Enqueue(opStack.pop());
}// end while
}// end else
opStack.push(digit);
break;
case '*':
case '/':
while(opStack.peek() == '*' || opStack.peek() == '/') {
//Pop operator and queue it
postQueue.Enqueue(opStack.pop());
}//end while
opStack.push(digit);
break;
case '(':
opStack.push(digit);
break;
case ')':
while(opStack.peek() != '(') {
//Pop operator and queue it
postQueue.Enqueue(opStack.pop());
}// end while
opStack.pop();
break;
} // End Switch Statement
infix.substring(1);
} // End While Statement
this.first = postQueue.GetFirst();
} // End Constructor
'''
The error occurs at "opStack.push(digit)"
The variable for the top error statement line 3511 is:
copyOf() is throwing OutOfMemoryError (id=20)
How can I fix this so that I can actually test if the logic throughout the rest of the class and other classes works?
I found the issue, I wasn't changing my loop condition by accident, down near the bottom the line infix.substring(1); should have been infix = infix.substring(1);, my program was trying to create an infinite stack of left parentheses.
I worked on a simple calculator app that does not pile up an expression like google calculator. Instead it stores the result in an operand when an operation button is pressed and so it does not follow BODMAS precedence rules. Like if I perform 2 + 2 / 2 I get 4 as the result whereas the result should be 3 as the division is performed first
Is there a way to take input as a whole expression and then evaluate it collectively?
Are there any predefined classes that I can use that are included in java?
The code for the onClickListeners of operators and calculation performing function is:
View.OnClickListener opListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
Button b = (Button) view;
String op = b.getText().toString();
String value = newNumber.getText().toString();
try {
Double doubleValue = Double.valueOf(value);
performOperation(doubleValue, op);
} catch (NumberFormatException e) {
newNumber.setText("");
}
pendingOperation = op;
displayOperation.setText(pendingOperation);
}
};
private void performOperation(Double value, String operation) {
if (operand1 == null) {
operand1 = value;
} else {
if (pendingOperation.equals("=")) {
pendingOperation = operation;
}
switch (pendingOperation) {
case "=":
operand1 = value;
break;
case "/":
if (value == 0) {
operand1 = 0.0;
Toast.makeText(this,"Cannot Divide By Zero, Resetting value to zero",Toast.LENGTH_LONG).show();
} else {
operand1 /= value;
}
break;
case "*":
operand1 *= value;
break;
case "+":
operand1 += value;
break;
case "-":
operand1 -= value;
break;
}
}
result.setText(operand1.toString());
newNumber.setText("");
}
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();
}
}
I am having trouble figuring out the logic for an infix calculator that is dynamic. I am able to accommodate string values with 5 elements, such as "1 + 1", but I cannot compute strings with more than 5 elements (ie: "1 + 2 + 3 + 4").
This is my process
import java.util.StringTokenizer;
public static int calculate(String input)
{
int lhs = 0;
int rhs = 0;
int total = 0;
char operation = ' ';
int intOne, intTwo;
StringTokenizer st = new StringTokenizer(input);
/*
* this block is chosen if there are no operations
*/
// block of if statement code for inputs less than or equal to
// 5 characters.
/*
* this block generates the correct number if there is more than
* one operator in the equation.
*/
}else if(input.length() > 5){
int firstValue = 0;
int latterValue = 0;
while(st.hasMoreTokens()){
/*
* method that assigns the left and right sides
*/
//assigns values to the first equation
int firstToken = Integer.parseInt(st.nextToken());
String opToken = st.nextToken();
int latterToken = Integer.parseInt(st.nextToken());
//returns a value for the first equation
firstValue = assignSides(firstToken, opToken, latterToken);
// takes in the next operator
if(st.nextToken().equals("+")){
operation = '+';
}else if(st.nextToken().equals("-")){
operation = '-';
}else if(st.nextToken().equals("*")){
operation = '*';
}else if(st.nextToken().equals("/")){
operation = '/';
}
// assigns values to the latter equation
firstToken = Integer.parseInt(st.nextToken());
opToken = st.nextToken();
latterToken = Integer.parseInt(st.nextToken());
//returns a value for the latter equation
latterValue = assignSides(firstToken, opToken, latterToken);
/*
* decides how to add the two equations
*/
switch(operation){
case '+': total = firstValue + latterValue;
break;
case '-': total = firstValue - latterValue;
break;
case '*': total = firstValue * latterValue;
break;
case '/': total = firstValue / latterValue;
break;
default: System.out.println("cannot compute");
break;
}
if(st.hasMoreTokens()){
//makes the total the first value
total = firstValue;
if(st.nextToken().equals("+")){
operation = '+';
}else if(st.nextToken().equals("-")){
operation = '-';
}else if(st.nextToken().equals("*")){
operation = '*';
}else if(st.nextToken().equals("/")){
operation = '/';
}
}
}
}
return total;
}
public static int assignSides(int firstToken, String opToken, int latterToken)
{
int lhs=0;
int rhs = 0;
int sum = 0;
char operation = ' ';
/*
* converts the string into a character
*/
if(opToken.equals("+")){
operation = '+';
}else if(opToken.equals("-")){
operation = '-';
}else if(opToken.equals("*")){
operation = '*';
}else if(opToken.equals("/")){
operation = '/';
}
rhs = latterToken;
/*
* interprates the character as a function
*/
switch(operation){
case '+': sum = lhs + rhs;
break;
case '-': sum = lhs - rhs;
break;
case '*': sum = lhs * rhs;
break;
case '/': sum = lhs / rhs;
break;
default: System.out.println("cannot compute");
break;
}
return sum;
}
Can I get help me with the error in my logic?
When calculating for more than 3 symbols (not counting spaces), as in "1 + 2 + 3",
you have to calculate in this order: 1 + (2 + 3).
You have to split up the first 1 and the remainig part "2 + 3", and pass the remaining part to the calculate method again. Something like:
int firstPart = ...; // evaluation of "1"
int secondPart = calculate("2 + 3");
int total = firstPart + secondPart;