I was trying to convert an expression from infix form to postfix form.I used String a, p , s for stack, postfix result expression, input expression respectively.
Every time I am getting this error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: -1 at
java.lang.String.charAt(String.java:658) at
javaapplication4.A.conversion(A.java:50) at
javaapplication4.A.main(A.java:83)
Please help me how can I solve it.
Here is my code:
import java.util.Scanner;
public class A {
String a="(", s = "", p = "";
int i, n = 1, top = 0, pp = 0;
void push(char ch) {
a = a + ch;
top = n;
n++;
}
void pop() {
n--;
top--;
}
int prio(char ch) {
int f = -1;
if (ch == '(') {
f = 0;
} else if (ch == '+' || ch == '-') {
f = 1;
} else if (ch == '*' || ch == '/' || ch == '%') {
f = 2;
} else if (ch == '^') {
f = 3;
}
return f;
}
void conversion() {
System.out.print("Enter infix form: ");
Scanner sd = new Scanner(System.in);
s = sd.nextLine();
//System.out.println(s);
int t, j, sz;
sz = s.length();
for (i = 0; i < sz; i++) {
if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
p = p + s.charAt(i);
pp++;
} else if (s.charAt(i) == '(') {
push('(');
} else if (s.charAt(i) == '-' || s.charAt(i) == '+' || s.charAt(i) == '*' || s.charAt(i) == '/' || s.charAt(i) == '%' || s.charAt(i) == '^') {
j = prio(s.charAt(i));
t = prio(a.charAt(top));
//System.out.println(t+" "+j);
while (j <= t) {
p = p + a.charAt(top);
pp++;
pop();
t = prio(a.charAt(top));
}
push(s.charAt(i));
} else if (s.charAt(i) == ')') {
while (a.charAt(top) != '(') {
p = p + a.charAt(top);
pp++;
pop();
}
pop();
}
}
while (a.charAt(top) != '(') {
p = p + a.charAt(top);
pp++;
pop();
}
pop();
}
void postfix() {
System.out.print("postfix form is: ");
System.out.println(p);
}
public static void main(String args[]) {
A h = new A();
h.conversion();
h.postfix();
//System.out.println(h.a);
//System.out.println(h.s);
}
}
Can you confirm if the error is here?
while (a.charAt(top) != '(')
Inside the loop you continuously pop(), which decrements from top, which has the risk of going negative if a match is never found. Even if the error is not here, it should check for that condition.
You may have made an extra pop() definition. Can you check this?
Related
This question already has answers here:
What is a NumberFormatException and how can I fix it?
(9 answers)
Closed 2 years ago.
When I try to use the function to iterate the user input expression, I get the java.lang.NumberFormatException, I try fixing the loop much time, but I still cannot understand where did it when wrong. The IDE suggest it went wrong in the parstInt while loop
Here is the code:
import java.util.Scanner;
import java.util.Stack;
static Stack<Integer> stackForOperand = new Stack<Integer>();
static Stack<Character> stackForOperator = new Stack<Character>();
public static int processOneOperator(char stackForOperator, int num1, int num2) {
int result = 0;
switch (stackForOperator) {
case '+':
result = num1 + num2;
case '-':
result = num1 - num2;
case '*':
result = num1 * num2;
case '/':
if (num2 != 0) {
result = num1 / num2;
} else {
throw new UnsupportedOperationException("divide by zero error");
}
}
return result;
}
public static boolean num_order(char first, char second) {
if (first == '(' || second == ')') {
return false;
} else if ((first == '*' || first == '/') && (second == '+' || second == '-')) {
return false;
} else {
return true;
}
}
public static int calculation_loop(String expression) {
for (int i = 0; i < expression.length(); i++) {
if (expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
String more_num = "";
while (i < expression.length() && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
more_num += expression.charAt(i++);
int more_num2 = Integer.parseInt(more_num);
stackForOperand.push(more_num2);
i--;
}
} else if (expression.charAt(i) == '(') {
stackForOperator.push(expression.charAt(i));
} else if (expression.charAt(i) == ')') {
while (stackForOperator.peek() != '(') {
stackForOperand.push(
processOneOperator(stackForOperator.pop(), stackForOperand.pop(), stackForOperand.pop()));
stackForOperator.pop();
}
} else if (expression.charAt(i) == '+' || expression.charAt(i) == '-' || expression.charAt(i) == '*'
|| expression.charAt(i) == '/') {
while (!stackForOperator.empty() && num_order(expression.charAt(i), stackForOperator.peek())) {
stackForOperand.push(
processOneOperator(stackForOperator.pop(), stackForOperand.pop(), stackForOperand.pop()));
stackForOperator.push(expression.charAt(i));
}
}
}
while (!stackForOperator.empty()) {
stackForOperand
.push(processOneOperator(stackForOperator.pop(), stackForOperand.pop(), stackForOperand.pop()));
}
return stackForOperand.pop();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("/");
String input = scanner.nextLine();
input = input.replaceAll("\\s+", "");
System.out.println(input);
Integer output = calculation_loop(input);
System.out.println(output);
}
}
Looking at this piece of code:
public static int calculation_loop(String expression) {
for (int i = 0; i < expression.length(); i++) {
if (expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
String more_num = "";
while (i < expression.length() && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
more_num += expression.charAt(i++);
int more_num2 = Integer.parseInt(more_num);
stackForOperand.push(more_num2);
i--;
}
So. Suppose having such an expression "2345+6789". According to your code i is incrementing and decrementing before end of while loop.
while (i < expression.length() && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
more_num += expression.charAt(i++);
...
i--;
}
Is this your intention? It makes your loop infinite and it finishes only because number format exception is thrown while parsing. This is why I think your parser throws exception: You got the digit '2' in first place, concatenate it with more_num, then increment the i, after that decrement the i and at the next iteration you have the same previous position with same char '2', then concatenate it again to more_num ad infinitum. And first you parse more_num which is "2", on next iteration you append one more '2' and more_num "22" then "222"... Till it become bigger than type int can hold like "22222222222222222222222" and exception is thrown
Second thing. Suppose you remove i-- and your loop will normally iterate the next char. So, your stackForOperand will push first the number 2, then will push the number 23 then the number 234, then will push the number 2345. Is that your intension? I think more logically is to move Integer.parseInt and stackForOperand.push after the while loop
public static int calculation_loop(String expression) {
for (int i = 0; i < expression.length(); i++) {
if (expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
String more_num = "";
while (i < expression.length() && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
more_num += expression.charAt(i++);
}
int more_num2 = Integer.parseInt(more_num);
stackForOperand.push(more_num2);
So basically before people start questioning why I'm not using a stack to save time over using counters and stuff.
This is a homework problem working with space complexity, so ignoring time complexity, we are attempting to reduce space complexity.
To do so, I have to use counters to keep track of the brackets.
Possible bracket types: '(' ')' '[' ']'
I've tried some coding but I seem to be having a problem with one of the test strings, and I just can't pinpoint where the problem is happening.
Boolean isWF(String w) {
// maxLevel is found and any variables I'm using has been initialized
for(int i = 0; i < maxLevel; i++) {
x = w.charAt(i);
currentLevel = i;
if(x == '(' || x == '[') {
holder = x; // Store bracket here to check match
savedLevel++;
counter++;
currentLevel++;
for(int j = i+1; j < w.length(); j++) {
x = w.charAt(j);
if(x == '(' || x == '[') {
currentLevel++;
if(currentLevel == savedLevel) {
holder = x;
counter++;
}
}
else if(x == ')' || x == ']') {
if(currentLevel == savedLevel) {
if((holder == '(' && x == ')') || (holder == '[' && x == ']')) {
currentLevel--;
counter--;
}
else
return false;
}
else {
currentLevel--;
}
}
}
}
else if(x == ')' || x == ']') {
counter--;
if(counter < 0) {
return false;
}
}
}
if(counter != 0) {
return false;
}
return true;
}
}
The strings I'm testing:
()[] - expected to be true, actual is true
([)] - expected to be false, actual is false
[([([()])])] - expected to be true, actual is true
([()([])()][()(())]()) - expected to be true, actual is false
([()([])())[()(())]()) - expected to be false, actual is false
Not a direct answer to where is the bug in your approach but the following approach seems to solve your input cases and is much simpler.
Basically you go over the string checking if the next symbol is one you can accept e.g. you can't accept a ) right after a [ and you keep a count of the open/close of brackets. If they ever go negative it means you are missing something.
public static boolean isBalanced(String s) {
int sOpen = 0;
int rOpen = 0;
for(int i = 0; i < s.length() - 1; ++i) {
final char current = s.charAt(i);
final char next = s.charAt(i + 1);
if(!isValidSymbol(current, next)) {
return false;
}
if(current == '(') rOpen++;
else if(current == '[') sOpen++;
else if(current == ')') rOpen--;
else if(current == ']') sOpen--;
if(rOpen < 0 || sOpen < 0) return false;
}
final char lastChar = s.charAt(s.length() - 1);
if(lastChar == '(') rOpen++;
else if(lastChar == '[') sOpen++;
else if(lastChar == ')') rOpen--;
else if(lastChar == ']') sOpen--;
return s.length() > 1 && rOpen == 0 && sOpen == 0;
}
private static boolean isValidSymbol(char from, char to) {
if(from == '(') {
return to == ')' || to == '[' || to == '(' ;
}
else if(from == '[') {
return to == ']' || to == '(' || to == '[';
}
return true;
}
public static void main(String[] args) {
String testInput = "()[]";
assert isBalanced(testInput) : "expected true";
testInput = "([)]";
assert isBalanced(testInput) == false : "expected false";
testInput = "[([([()])])]";
assert isBalanced(testInput) : "expected true";
testInput = "([()([])()][()(())]())";
assert isBalanced(testInput) : "expected true";
testInput = "([()([])())[()(())]()) ";
assert isBalanced(testInput) == false : "expected false";
}
import java.util.Stack;
import java.util.Scanner;
public class CheckValidLocationofParenthensies {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter five data");
String input1 = scanner.next();
balancedParenthensies(input1);
}
public static boolean balancedParenthensies(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c == '[' || c == '(' || c == '{' ) {
stack.push(c);
if(c == '[') {
newvalueforforward(s,']', i);
}
if(c == '{') {
newvalueforforward(s,'}', i);
}
if(c == '(') {
newvalueforforward(s,')', i);
}
} else if(c == ']') {
if(stack.isEmpty() || stack.pop() != '[') {
newvalue(s,'[', i);
return false;
}
} else if(c == ')') {
if(stack.isEmpty() || stack.pop() != '(') {
newvalue(s,'(', i);
return false;
}
} else if(c == '}') {
if(stack.isEmpty() || stack.pop() != '{') {
newvalue(s,'{', i);
return false;
}
}
}
return stack.isEmpty();
}
public static void newvalueforforward(String userval,char value,int decremntval) {
for(int i = 0; i < userval.length(); i++){
StringBuilder newvalue = new StringBuilder(userval);
int location=i;
newvalue.insert(i, value);
boolean valid= checkingnewvalueisValidorNot(newvalue, location);
location=i+1;
if(valid) {
System.out.println(newvalue+" "+""+location);
}
}
}
public static void newvalue(String userval,char value,int decremntval) {
for(int i = decremntval; i >= 0; i--){
StringBuilder newvalue = new StringBuilder(userval);
int location=decremntval - i;
newvalue.insert(decremntval - i, value);
boolean valid= checkingnewvalueisValidorNot(newvalue, location);
if(valid) {
System.out.println(newvalue+" "+""+location);
}
}
}
public static boolean checkingnewvalueisValidorNot(StringBuilder userval,int validpath) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < userval.length(); i++) {
char c = userval.charAt(i);
if(c == '[' || c == '(' || c == '{' ) {
stack.push(c);
} else if(c == ']') {
if(stack.isEmpty() || stack.pop() != '[') {
return false;
}
} else if(c == ')') {
if(stack.isEmpty() || stack.pop() != '(') {
return false;
}
} else if(c == '}') {
if(stack.isEmpty() || stack.pop() != '{') {
return false;
}
}
}
return stack.isEmpty();
}
}
Above is the code i have written to check whether input string contains all balanced brackets if it is not balanced then get missing bracket and place bracket in all index then again check whether string is balanced or not.
I got valid output but problem is between i bracket there should be a intergers
here is input and outputs
input missing outputs
{[(2+3)*6/10} ] {[](2+3)*6/10} 3 not valid(no numbres btn bracket)
{[(2+3)]*6/10} 8 valid
{[(2+3)*]6/10} 9 not valid(after * no number)
{[(2+3)*6]/10} 10 valid
{[(2+3)*6/]10} 11 not valid( / before bracket)
{[(2+3)*6/1]0} 12 not valid( / btn num bracket)
{[(2+3)*6/10]} 13 valid
i am failing to do proper validation to my output.
Before the bracket there may be:
number
closing bracket
After the bracket there may be:
operator
closing bracket
end of expression
(ignoring any whitespace)
I need to find the number of distinct vowels. I came up with the code below but it can't make distinction between same vowels:
public static int count_Vowels(String str) {
str = str.toLowerCase();
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == 'a' || str.charAt(i) == 'e' || str.charAt(i) == 'i'
|| str.charAt(i) == 'o' || str.charAt(i) == 'u') {
count++;
}
}
return count;
}
I would start with five variables (one for each vowel) set to 0, iterate the characters in the input and set the corresponding variable to 1 if I find a match, and simply return the accumulated value of said variables. Like,
public static int count_Vowels(String str) {
int a = 0, e = 0, i = 0, o = 0, u = 0;
for (char ch : str.toLowerCase().toCharArray()) {
if (ch == 'a') {
a = 1;
} else if (ch == 'e') {
e = 1;
} else if (ch == 'i') {
i = 1;
} else if (ch == 'o') {
o = 1;
} else if (ch == 'u') {
u = 1;
}
}
return a + e + i + o + u;
}
You could use Set data structure and instead of incrementing the counter just add vowels to the set. At the end you can return just the size of the set.
The problem in your code is that you are not counting the distinct vowels, but all the vowels in the string. A Java-8 way to this:
public static int countDistinctVowels(String str) {
str = str.toLowerCase();
int count = (int) str.chars() // get IntStream of chars
.mapToObj(c -> (char) c) // cast to char
.filter(c -> "aeiou".indexOf(c) > -1) // remove all non-vowels
.distinct() // keep the distinct values
.count(); // count the values
return count;
}
Also use proper Java naming conventions: countDistinctVowels, no count_Distinct_Vowels.
there's definitely an issue here with this counting. at the very least. you should rethink this:
if (str.charAt(i) == 'a' || str.charAt(i) == 'e' || str.charAt(i) == 'i'
|| str.charAt(i) == 'o' || str.charAt(i) == 'u')
count++;
You could use the method contains
public static int count_Vowels(String str) {
str = str.toLowerCase();
int count = 0;
count += string.contains("a") ? 1 : 0;
count += string.contains("e") ? 1 : 0;
count += string.contains("i") ? 1 : 0;
count += string.contains("o") ? 1 : 0;
count += string.contains("u") ? 1 : 0;
return count;
}
I made explanations in the comments to the code:
public static int count_Vowels(String str) {
str = str.toLowerCase();
Set<Character> setOfUsedChars = new HashSet<>(); // Here you store used vowels
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == 'a' || str.charAt(i) == 'e' || str.charAt(i) == 'i'
|| str.charAt(i) == 'o' || str.charAt(i) == 'u') { // if currently checked character is vowel...
setOfUsedChars.add(str.charAt(i)); // add this vowel to setOfUsedChars
}
}
return setOfUsedChars.size(); // size of this sets is a number of vowels present in input String
}
static void vow(String input){
String output=input.toLowerCase();
int flaga=0,flage=0,flagi=0,flago=0,flagu=0;
for(int i=0;i<input.length();i++) {
if((output.charAt(i))=='a' && flaga==0) {
System.out.print(input.charAt(i)+" ");
flaga++;
}
if(output.charAt(i)=='e' && flage==0) {
System.out.print(input.charAt(i)+" ");
flage++;
}
if(output.charAt(i)=='i' && flagi==0) {
System.out.print(input.charAt(i)+" ");
flagi++;
}
if(output.charAt(i)=='o' && flago==0) {
System.out.print(input.charAt(i)+" ");
flago++;
}
if(output.charAt(i)=='u' && flagu==0) {
System.out.print(input.charAt(i)+" ");
flagu++;
}
}
}
public static void main(String args[]) {
String sentence;
int v=0,c=0,ws=0;
Scanner sc= new Scanner(System.in);
sentence = sc.nextLine();
sc.close();
sentence.toLowerCase();
String res="";
for(int i=0;i<sentence.length();i++) {
if(sentence.charAt(i)=='a'||sentence.charAt(i)=='e'||sentence.charAt(i)=='i'||sentence.charAt(i)=='o'||sentence.charAt(i)=='u') {
if(res.indexOf(sentence.charAt(i))<0) {
res+=sentence.charAt(i);
v++;
}//System.out.println(res.indexOf(sentence.charAt(i)));
}
else if(sentence.charAt(i)==' ')
ws++;
else c++;
}
System.out.println(res);
System.out.println("no of vowels: "+v+"\n"+"no of consonants: "+c+"\n"+"no of
white spaces: "+ws);
}
You can use this Method to Find Count of Distinct vowels.
public static int count_Vowels(String str) {
char[] c = str.toLowerCase().toCharArray();
int Counter=0;
String NewString="";
for(int i=0;i<c.length;i++){
String tempString="";
tempString+=c[i];
if(!NewString.contains(tempString) && (c[i]=='a'||c[i]=='e'||c[i]=='i'||c[i]=='o'||c[i]=='u')){
Counter++;
NewString+=c[i];
}
}
return Counter;
}
Here is a solve for this problem without using objects. It's a crude but great solve for beginners who encounter this problem with limited js experience.
How to count unique vowels is a string;
function hasUniqueFourVowels(str){
let va = 0
let ve = 0
let vi = 0
let vo = 0
let vu = 0
let sum = 0
for(let i = 0; i < str.length; i++){
let char = str[i];
if(char === "i"){
vi = 1
}
if(char === "e"){
ve = 1
}
if(char === "a"){
va = 1
}
if(char === "o"){
vo = 1
}
if(char === "u"){
vu = 1
}
sum = va + vi + vo + ve + vu
if (sum >= 4){
return true
}
}
return false
}
#Test
public void numfindVoweles(){
String s="aeiouaedtesssiou";
char a[]=s.toCharArray();
HashMap<Character,Integer> hp= new HashMap<Character, Integer>();
for(char ch:a){
if(hp.containsKey(ch) && (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u')){
hp.put(ch,hp.get(ch)+1);
}
else if(ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u'){
hp.put(ch,1);
}
}
System.out.println(hp);
}
Maybe some one can help?
How to modify this method next() that the next token can be: 'abc' text with the quotes.
Now if the text contains quote are throwed ExpressionException Unknown operator ''' at position...
#Override
public String next() {
StringBuilder token = new StringBuilder();
if (pos >= input.length()) {
return previousToken = null;
}
char ch = input.charAt(pos);
while (Character.isWhitespace(ch) && pos < input.length()) {
ch = input.charAt(++pos);
}
if (Character.isDigit(ch)) {
while ((Character.isDigit(ch) || ch == decimalSeparator)
&& (pos < input.length())) {
token.append(input.charAt(pos++));
ch = pos == input.length() ? 0 : input.charAt(pos);
}
} else if (ch == minusSign
&& Character.isDigit(peekNextChar())
&& ("(".equals(previousToken) || ",".equals(previousToken)
|| previousToken == null || operators
.containsKey(previousToken))) {
token.append(minusSign);
pos++;
token.append(next());
} else if (Character.isLetter(ch)) {
while ((Character.isLetter(ch) || Character.isDigit(ch) || (ch == '_')) && (pos < input.length())) {
token.append(input.charAt(pos++));
ch = pos == input.length() ? 0 : input.charAt(pos);
}
} else if (ch == '(' || ch == ')' || ch == ',') {
token.append(ch);
pos++;
//FIXME
else if (ch == '\''){
pos++;
String temp = "\'"+next()+"\'";
token.append(temp);
pos++;
}
//
} else {
while (!Character.isLetter(ch) && !Character.isDigit(ch)
&& !Character.isWhitespace(ch) && ch != '('
&& ch != ')' && ch != ',' && (pos < input.length())) {
token.append(input.charAt(pos));
pos++;
ch = pos == input.length() ? 0 : input.charAt(pos);
if (ch == minusSign) {
break;
}
}
if (!operators.containsKey(token.toString())) {
throw new ExpressionException("Unknown operator '" + token
+ "' at position " + (pos - token.length() + 1));
}
}
return previousToken = token.toString();
}
eval
public Object eval() {
Stack<Object> stack = new Stack<Object>();
for (String token : getRPN()) {
mylog.pl("Reverse polish notation TOKEN : " + token + " RPN size: " + getRPN().size() );
if (operators.containsKey(token)) {
Object v1 = stack.pop();
Object v2 = stack.pop();
stack.push(operators.get(token).eval(v2, v1));
} else if (variables.containsKey(token)) {
stack.push(variables.get(token).round(mc));
} else if (functions.containsKey(token.toUpperCase())) {
Function f = functions.get(token.toUpperCase());
ArrayList<Object> p = new ArrayList<Object>(f.getNumParams());
for (int i = 0; i < f.numParams; i++) {
p.add(0, stack.pop());
}
Object fResult = f.eval(p);
stack.push(fResult);
} else if (isDate(token)) {
Long date = null;
try {
date = SU.sdf.parse(token).getTime();
} catch (ParseException e) {/* IGNORE! */
}
stack.push(new BigDecimal(date, mc));
} else {
if (BusinessStrategy.PREFIX_X.equals(Character.toString(token.charAt(0)))) {
stack.push(token);
} else {
stack.push(new BigDecimal(token, mc));
}
}
}
return stack.pop();
}
Reverse notation
private List<String> getRPN() {
if (rpn == null) {
rpn = shuntingYard(this.expression);
}
return rpn;
}
Yard
private List<String> shuntingYard(String expression) {
List<String> outputQueue = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
Tokenizer tokenizer = new Tokenizer(expression);
String lastFunction = null;
while (tokenizer.hasNext()) {
String token = tokenizer.next();
if (isNumber(token)) {
outputQueue.add(token);
} else if (variables.containsKey(token)) {
outputQueue.add(token);
} else if (functions.containsKey(token.toUpperCase())) {
stack.push(token);
lastFunction = token;
} else if (Character.isLetter(token.charAt(0))) {
if ("\'".equals(Character.toString(token.charAt(0)))){
outputQueue.add(token);
} else {
stack.push(token);
}
} else if (",".equals(token)) {
while (!stack.isEmpty() && !"(".equals(stack.peek())) {
outputQueue.add(stack.pop());
}
if (stack.isEmpty()) {
throw new ExpressionException("Parse error for function '"
+ lastFunction + "'");
}
} else if (operators.containsKey(token)) {
Operator o1 = operators.get(token);
String token2 = stack.isEmpty() ? null : stack.peek();
while (operators.containsKey(token2)
&& ((o1.isLeftAssoc() && o1.getPrecedence() <= operators
.get(token2).getPrecedence()) || (o1
.getPrecedence() < operators.get(token2)
.getPrecedence()))) {
outputQueue.add(stack.pop());
token2 = stack.isEmpty() ? null : stack.peek();
}
stack.push(token);
} else if ("(".equals(token)) {
stack.push(token);
} else if (")".equals(token)) {
while (!stack.isEmpty() && !"(".equals(stack.peek())) {
outputQueue.add(stack.pop());
}
if (stack.isEmpty()) {
throw new RuntimeException("Mismatched parentheses");
}
stack.pop();
if (!stack.isEmpty()
&& functions.containsKey(stack.peek().toUpperCase())) {
outputQueue.add(stack.pop());
}
}
}
while (!stack.isEmpty()) {
String element = stack.pop();
if ("(".equals(element) || ")".equals(element)) {
throw new RuntimeException("Mismatched parentheses");
}
if (!operators.containsKey(element)) {
throw new RuntimeException("Unknown operator or function: "
+ element);
}
outputQueue.add(element);
}
return outputQueue;
}
Error
*java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at com.business.Expression.eval(Expression.java:1033)*
It is in eval method Object v1 = stack.pop(); line.
Thanks !
In method next you have recursive calls in two places:
after seeing a minus sign
after recognizing an apostrope
The first situation will construct tokens where a minus is followed by a digit (i.e., an unsigend number follows) - OK. (Although, not having a sign but an unary minus operator deserves some consideration.)
The second scenario means trouble. After advancing past the initial apostrophe, another next-result is expected, as if string literals would only contain one number or one identifier or a single operator. Anyway, the next() executes, let's say it returns a number: then an apostroph is added to the token, but there's no effort to check whether there is a closing apostrophe nor to skip that.
else if (ch == '\''){
token.append( '\'' );
pos++;
while( pos < input.length() &&
(ch = input.charAt(pos++)) != '\'' ){
token.append( ch );
}
token.append( '\'' );
This doesn't permit an apostrophe to be a character within the string and it does not diagnose an unterminated string. But this can be added rather easily.