如何修改仅支持单数字的递归Java计算器以适配多数字运算?
Hey there! The main reason your calculator only handles single-digit numbers is that your factor() method reads just one digit and calls it a day. Let's fix that—we'll adjust the method to read consecutive digits and combine them into a full number, while keeping your existing recursive structure for operator precedence intact.
Key Modification: Update the factor() Method
Right now, factor() checks for a single digit, converts it, and moves on. To support multi-digit numbers, we need to:
- When we encounter a digit, keep reading subsequent characters as long as they're digits.
- Combine these digits into a single integer (e.g., '1' followed by '2' becomes 12).
Modified Code
Here's the updated version of your calculator with multi-digit support. I've highlighted the critical changes and included the required ParseError class for completeness:
import java.io.IOException; import java.io.InputStream; public class Calculator { private int lookAheadToken; private InputStream inputStream; public Calculator(InputStream inputStream) throws IOException, ParseError { this.inputStream = inputStream; lookAheadToken = inputStream.read(); } private void consume(int symbol) throws IOException, ParseError { if (lookAheadToken != symbol) throw new ParseError(); lookAheadToken = inputStream.read(); } private int evalDigit(int digit) { return digit - '0'; } private void goal() throws ParseError, IOException { int result = expr(); if (lookAheadToken == '\n') { System.out.println("result = " + result); } consume(lookAheadToken); if (lookAheadToken == -1) return; goal(); } private int expr() throws ParseError, IOException { int result = term(); return rest_expr(result); } private int rest_expr(int factor) throws ParseError, IOException { if (lookAheadToken == '\n' || lookAheadToken == ')' || lookAheadToken == -1) return factor; if (lookAheadToken != '+' && lookAheadToken != '-') throw new ParseError(); char operator = (char) lookAheadToken; consume(lookAheadToken); int result = term(); if (operator == '+') { return rest_expr(factor + result); } else if (operator == '-') { return rest_expr(factor - result); } else return factor; } private int term() throws ParseError, IOException { int result = factor(); return rest_term(result); } private int rest_term(int factor) throws ParseError, IOException { if (lookAheadToken == '\n' || lookAheadToken == ')' || lookAheadToken == -1) return factor; if (lookAheadToken == '+' || lookAheadToken == '-') return factor; if (lookAheadToken != '*' && lookAheadToken != '/') throw new ParseError(); char operator = (char) lookAheadToken; consume(lookAheadToken); int result = factor(); if (operator == '*') { return rest_term(factor * result); } else if (operator == '/') { return rest_term(factor / result); } return factor; } // Updated to handle multi-digit numbers private int factor() throws ParseError, IOException { if (lookAheadToken == '(') { consume(lookAheadToken); int result = expr(); if (lookAheadToken == ')') { consume(lookAheadToken); return result; } else throw new ParseError(); } if (lookAheadToken < '0' || lookAheadToken > '9') throw new ParseError(); // Build the full multi-digit number int number = 0; while (lookAheadToken >= '0' && lookAheadToken <= '9') { number = number * 10 + evalDigit(lookAheadToken); consume(lookAheadToken); } return number; } public static void main(String[] args) throws IOException, ParseError { InputStream inputStream = System.in; Calculator calculator = new Calculator(inputStream); calculator.goal(); } } // Required ParseError exception class class ParseError extends Exception { public ParseError() { super("Invalid expression syntax"); } }
What Changed?
- Revised
factor(): Instead of reading one digit, we initialize anumbervariable to 0. We then loop as long as the next token is a digit:- Multiply the current number by 10 (to shift existing digits left, e.g., 1 becomes 10 when we read a '2')
- Add the value of the new digit
- Consume the digit token and repeat until we hit a non-digit character
- Added
ParseErrorclass: Included it since your original code noted it's required for error handling.
Testing It Out
Try these test cases to verify the fix:
123+45→ Outputsresult = 1689*87-6→ Outputsresult = 777(10+20)*3→ Outputsresult = 90
This preserves your original recursive logic for operator precedence and parentheses, while adding full support for multi-digit numbers.
内容的提问来源于stack exchange,提问作者vasilis_dim

