gpt4 book ai didi

Java计算器因输入括号而崩溃

转载 作者:行者123 更新时间:2023-12-02 05:51:37 25 4
gpt4 key购买 nike

帮助我 stackoverflow,你是我唯一的希望。我一直在尝试制作一个简单的计算器,终于我成功了!问题是只计算简单的表达式。例如:4*5 将给出 20.0。 (太棒了!)

每当我给它一个更复杂的表达式(如 4*(2+3))时,程序就会因 EmptyStackException 而崩溃。我理解这个异常,但是当我用我的大脑和一张纸手动运行代码时,我无法在脑海中重现问题。

谁能弄清楚为什么会崩溃吗?这是完整的代码。我用一些粗体、全大写的单词标记了代码崩溃的地方。 (即程序在这里崩溃)

/**
* Human
* Project 3: SUPER-DUPER JAVA CALCULATOR
*/

import java.util.*;
import java.util.Stack;
import java.lang.String;
import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashSet;
import java.lang.Exception;
import java.lang.Math;

public class InfixEvaluator {

public static class SyntaxErrorException extends Exception {
/**
* Construct a SyntaxErrorException with the specified message.
*
* @param message The message
*/
SyntaxErrorException(String message) {
super(message);
}
}

/**
* This is the stack of operands:
* i.e. (doubles/parentheses/brackets/curly braces)
*/
private static Stack<Double> operandStack = new Stack<Double>();

/**
* This is the operator stack
* i.e. (+-/*%^)
*/
private static Stack<String> operatorStack = new Stack<String>();

/**
* These are the possible operators
*/
private static final String OPERATORS = "+-/*%^()[]{}";
private static final String BRACES = "()[]{}";
private static final String NONBRACES = "+-/*%^";
private static final int[] PRECEDENCE = {1, 1, 2, 2, 2, -1, -1, -1, -1, -1, -1};
/**
* This is an ArrayList of all the discrete
* things (operators/operands) making up an input.
* This is really just getting rid of the spaces,
* and dividing up the "stuff" into manageable pieces.
*/
static ArrayList<String> input = new ArrayList<String>();

public static ArrayList inputCleaner(String postfix) {
StringBuilder sb = new StringBuilder();
String noSpaces = postfix.replace(" ", "");
try {
for (int i = 0; i < noSpaces.length(); i++) {
char c = noSpaces.charAt(i);
boolean isNum = (c >= '0' && c <= '9');

if (isNum) {
sb.append(c);
if (i == noSpaces.length() - 1) {
input.add(sb.toString());
sb.delete(0, sb.length());
}
} else if (c == '.') {
for (int j = 0; j < sb.length(); j++) {
if (sb.charAt(j) == '.') {
throw new SyntaxErrorException("You can't have two decimals in a number.");
} else if (j == sb.length() - 1) {
sb.append(c);
j = (sb.length() + 1);
}
}
if (sb.length() == 0) {
sb.append(c);
}
if (i == noSpaces.length() - 1) {
throw new SyntaxErrorException("You can't end your equation with a decimal!");
}
} else if (OPERATORS.indexOf(c) != -1) {
if (sb.length() != 0) {
input.add(sb.toString());
sb.delete(0, sb.length());
}
sb.append(c);
input.add(sb.toString());
sb.delete(0, sb.length());
} else {
throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
}
}

int numLP = 0;
int numRP = 0;
int numLB = 0;
int numRB = 0;
int numLBr = 0;
int numRBr = 0;

for (int f = 0; f < input.size(); f++) {
String trololol = input.get(f);

switch (trololol) {
case "(":
numLP++;
break;
case "[":
numLB++;
break;
case "{":
numLBr++;
break;
case ")":
numRP++;
break;
case "]":
numRB++;
break;
case "}":
numRBr++;
break;
default: //do nothing
break;
}

}
if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
}

int doop = 0;
int scoop = 0;
int foop = 0;
for (int f = 0; f < input.size(); f++) {
String awesome = input.get(f);
switch (awesome) {
case "(":
doop++;
break;
case "[":
scoop++;
break;
case "{":
foop++;
break;
case ")":
doop--;
break;
case "]":
scoop--;
break;
case "}":
foop--;
break;
default: //do nothing
break;
}
if (doop < 0 || scoop < 0 || foop < 0) {
throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
}
}
if (NONBRACES.indexOf(input.get(input.size() - 1)) != -1) {
throw new SyntaxErrorException("The input can't end in an operator");
}
return input;
} catch (SyntaxErrorException ex) {
System.out.println(ex);
return input;
}
}

/**
* Method to process operators
*
* @param op The operator
* @throws EmptyStackException
*/
private static void processOperator(String op) {
if (operatorStack.empty() || op == "(" || op == "[" || op == "{") {
operatorStack.push(op);
} else {
//peek the operator stack and
//let topOp be the top operator.
String topOp = operatorStack.peek();
if (precedence(op) > precedence(topOp)) {
operatorStack.push(op);
} else {
//Pop all stacked operators with equal
// or higher precedence than op.
while (!operatorStack.empty() && precedence(op) <= precedence(topOp)) {
double r = operandStack.pop();
double l = operandStack.pop();
String work = operatorStack.pop();
switch (work) {
case "+":
operandStack.push(l + r);
break;
case "-":
operandStack.push(l - r);
break;
case "*":
operandStack.push(l * r);
break;
case "/":
operandStack.push(l / r);
break;
case "%":
operandStack.push(l % r);
break;
case "^":
operandStack.push(Math.pow(l, r));
break;
default: //do nothing, but this should never happen
break;
}

if (topOp == "(" || topOp == "[" || topOp == "{") {
//matching '(' popped - exit loop.
operandStack.push(l);
operandStack.push(r);
break;
}

if (!operatorStack.empty()) {
//reset topOp
topOp = operatorStack.peek();
}
}

//assert: Operator stack is empty or
// current operator precedence > top of stack operator precedence.
if (op != ")" || op != "]" || op != "}") {
operatorStack.push(op);
}
}
}
}

public static String infixCalculator(ArrayList<String> puke) {
int p;
for (p = 0; p < puke.size(); p++) {
if (OPERATORS.indexOf(puke.get(p)) == -1) {
double herp = Double.parseDouble(puke.get(p));
operandStack.push(herp);
} else {
processOperator(puke.get(p));
}
}
if (p == puke.size()) {
while (!operatorStack.empty()) {
double r = operandStack.pop();
double l = operandStack.pop();
String work = operatorStack.pop();
switch (work) {
case "+":
operandStack.push(l + r);
break;
case "-":
operandStack.push(l - r);
break;
case "*":
operandStack.push(l * r);
break;
case "/":
operandStack.push(l / r);
break;
case "%":
operandStack.push(l % r);
break;
case "^":
operandStack.push(Math.pow(l, r));
break;
default:
break;
}
}
}
return String.valueOf(operandStack.pop());
}

private static int precedence(String op) {
return PRECEDENCE[OPERATORS.indexOf(op)];
}

public static void main(String[] args) {

do {
try {
ArrayList test = new ArrayList();
Scanner f = new Scanner(System.in);


System.out.println("Please insert an argument: \n");


String g = f.nextLine();

test = inputCleaner(g);

for (int z = 0; z < test.size(); z++) {
System.out.println(test.get(z));
}

System.out.println(infixCalculator(test));

test.clear();
} catch (EmptyStackException e) {
System.out.println("Make sure you only put in operators and operands.");
}
} while (true);
}
}

堆栈跟踪:

java.util.EmptyStackException at 
java.util.Stack.peek(Stack.java:102) at
java.util.Stack.pop(Stack.java:84) at
InfixEvaluator.processOperator(InfixEvaluator.java:177) at
InfixEvaluator.infixCalculator(InfixEvaluator.java:225) at
InfixEvaluator.main(InfixEvaluator.java:276)

最佳答案

您的错误来自于当堆栈为空时从堆栈中弹出元素。因此得名 EmptyStackException

我注意到在你的循环中你说了类似 while(!operatorStack.empty()) 的内容,但随后在 while 循环中你从堆栈中弹出 2 个或有时 3 个元素。如果您想从数组中弹出更多元素,您应该在 while 循环中测试该元素。

因此,如果弹出 2 个元素,则执行 while (operatorStack.size() > 2 )。我编辑了您的代码,将所有 while 循环更改为正确的,并且它对于这些输入运行良好

(2+3)(2+3)+5

这是我所做的:

  • 将样板代码移至新方法中
  • 添加了方法签名注释
  • 修复了运算符优先级,pow 运算符的优先级错误。
  • 将很多地方的字符串比较从 str1 == str2 更改为 str1.equals(str2)。你应该看看How do I compare strings in Java?看看我为什么这么做。
  • 添加了 System.out.println 语句来调试您的应用程序。我把它们留在里面,这样你就可以看到输出并亲自检查。你应该仔细看看我做了什么,以帮助你将来调试。
<小时/>
import java.util.*;
import java.util.Stack;
import java.lang.String;
import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashSet;
import java.lang.Exception;
import java.lang.Math;

public class InfixEvaluator
{

public static class SyntaxErrorException extends Exception {
/** Construct a SyntaxErrorException with the specified message.
@param message The message
*/
SyntaxErrorException(String message) {
super(message);
}
}
/** This is the stack of operands:
i.e. (doubles/parentheses/brackets/curly braces)
*/
private static Stack<Double> operandStack = new Stack<Double>();

/** This is the operator stack
* i.e. (+-/*%^)
*/
private static Stack<String> operatorStack = new Stack<String>();

/** These are the possible operators */
private static final String OPERATORS = "+-/*%^()[]{}";
private static final String BRACES = "()[]{}";
private static final String NONBRACES = "+-/*%^";
// + - / * % ^ ( ) [ ] { }
private static final int[] PRECEDENCE = {1, 1, 2, 2, 3, 3, -1, -1, -1, -1, -1, -1};
/** This is an ArrayList of all the discrete
things (operators/operands) making up an input.
This is really just getting rid of the spaces,
and dividing up the "stuff" into manageable pieces.
*/
static ArrayList<String> input = new ArrayList<String>();

/**
* TODO: write this
* @param postfix
* @return
*/
public static ArrayList inputCleaner(String postfix){
StringBuilder sb = new StringBuilder();
String noSpaces = postfix.replace(" ", "");
try {
for (int i = 0; i < noSpaces.length(); i++) {
char c = noSpaces.charAt(i);
boolean isNum = (c >= '0' && c <= '9');

if (isNum) {
sb.append(c);
if (i == noSpaces.length()-1) {
input.add(sb.toString());
sb.delete(0, sb.length());
}
} else if (c == '.') {
for (int j = 0; j < sb.length(); j++) {
if (sb.charAt(j) == '.') {
throw new SyntaxErrorException("You can't have two decimals in a number.");
} else if (j == sb.length() - 1) {
sb.append(c);
j = (sb.length() + 1);
}
}
if (sb.length() == 0) {
sb.append(c);
}
if (i == noSpaces.length()-1) {
throw new SyntaxErrorException("You can't end your equation with a decimal!");
}
} else if (OPERATORS.indexOf(c)!= -1) {
if (sb.length() != 0) {
input.add(sb.toString());
sb.delete(0, sb.length());
}
sb.append(c);
input.add(sb.toString());
sb.delete(0, sb.length());
} else {
throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
}
}

int numLP = 0;
int numRP = 0;
int numLB = 0;
int numRB = 0;
int numLBr = 0;
int numRBr = 0;

for (int f = 0; f < input.size(); f++) {
switch (input.get(f)) {
case "(": numLP++;
break;
case "[": numLB++;
break;
case "{": numLBr++;
break;
case ")": numRP++;
break;
case "]": numRB++;
break;
case "}": numRBr++;
break;
default: //do nothing
break;
}

}
if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
}

int doop = 0;
int scoop = 0;
int foop = 0;
for (int f = 0; f < input.size(); f++) {
String awesome = input.get(f);
switch (awesome) {
case "(": doop++;
break;
case "[": scoop++;
break;
case "{": foop++;
break;
case ")": doop--;
break;
case "]": scoop--;
break;
case "}": foop--;
break;
default: //do nothing
break;
}
if (doop < 0 || scoop < 0 || foop < 0) {
throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
}
}
if (NONBRACES.indexOf(input.get(input.size()-1)) != -1) {
throw new SyntaxErrorException("The input can't end in an operator");
}
return input;
} catch (SyntaxErrorException ex) {
System.out.println(ex);
return input;
}
}

/**Method to process operators
* @param op The operator
* @throws SyntaxErrorException
* @throws EmptyStackException
*/
private static void processOperator(String op) throws SyntaxErrorException {
if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
operatorStack.push(op);
} else {
//peek the operator stack and
//let topOp be the top operator.
String topOp = operatorStack.peek();
if (precedence(op) > precedence(topOp)) {
topOp = op;
operatorStack.push(op);
} else {
System.out.println(operatorStack);
System.out.println(operandStack);
System.out.println("--------------");
//Pop all stacked operators with equal
// or higher precedence than op.
while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
double r = operandStack.pop();
double l = operandStack.pop();
String work = getNextNonBracerOperator();
System.out.println("L:" + l + " R:" + r + " W:" + work);

doOperandWork(work, l, r);

if(op.equals("(") || op.equals("[") || op.equals("{")) {
//matching '(' popped - exit loop.
operandStack.push(l);
operandStack.push(r);
break;
}

if (!operatorStack.empty()) {
//reset topOp
topOp = operatorStack.peek();
}
}

//assert: Operator stack is empty or
// current operator precedence > top of stack operator precedence.
if(!op.equals(")") || !op.equals("}") || !op.equals("}")) {
operatorStack.push(op);
}
}
}
}

/**
* TODO: write this
* @param expressions
* @return
* @throws SyntaxErrorException
*/
public static String infixCalculator(ArrayList<String> expressions) throws SyntaxErrorException {
for (String expression : expressions) {
if (OPERATORS.indexOf(expression) == -1) {
operandStack.push(Double.parseDouble(expression));
} else {
processOperator(expression);
}
}
while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
System.out.println("--------------");
System.out.println(operandStack);
System.out.println(operatorStack);

double r = operandStack.pop();
double l = operandStack.pop();
String work = getNextNonBracerOperator();
System.out.println("L:" + l + " R:" + r + " W:" + work);

doOperandWork(work, l, r);
}
if(operandStack.isEmpty())
return null;
return String.valueOf(operandStack.pop());
}

/**
* goes through the stack and pops off all non operatable operations until it gets to one that is in the NONBRACES String
* @return The next operatable string
*/
private static String getNextNonBracerOperator() {
String work = "\0"; // \0 is null,
while(!operatorStack.isEmpty() && NONBRACES.indexOf(work) == -1)
work = operatorStack.pop();
return work;
}

/**
*
* @param work The operator you want to work. This really should be a character but its still a string
* @param l Left side number
* @param r Right side number
* @throws SyntaxErrorException If the operator could not be found
*/
private static void doOperandWork(String work, double l, double r) throws SyntaxErrorException {
switch (work) {
case "+": operandStack.push(l+r);
break;
case "-": operandStack.push(l-r);
break;
case "*": operandStack.push(l*r);
break;
case "/": operandStack.push(l/r);
break;
case "%": operandStack.push(l%r);
break;
case "^": operandStack.push(Math.pow(l, r));
break;
default:
throw new SyntaxErrorException("Invalid operand " + work);
}
}

/**
* @param op The operator
* @return the precedence
*/
private static int precedence(String op) {
return PRECEDENCE[OPERATORS.indexOf(op)];
}

public static void main(String[] args) {
try {
ArrayList test = new ArrayList();
Scanner f = new Scanner(System.in);

//System.out.println("Please insert an argument: ");

//String g = f.nextLine();
//String g = "(1+1)^(3+1)";
String g = "(1+3)*3^2+2*4-1";
test = inputCleaner(g);

for (int z = 0; z < test.size(); z++) {
System.out.println(test.get(z));
}

System.out.println(infixCalculator(test));

test.clear();
} catch (SyntaxErrorException e) {
System.out.println("Make sure you only put in operators and operands.");
e.printStackTrace();
}
}
}

关于Java计算器因输入括号而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23485768/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com