You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中替代C++ std::cin.unget()的方案咨询

Java替代C++ std::cin.unget()的方案(适配表达式解析场景)

你要把一段C数学表达式解析代码转成Java,但C里用到的std::cin.unget()在Java中没有直接对应的方法。先明确C++里unget()的作用:它会把刚读取的字符放回输入流,让下一次读取操作能重新获取这个字符——比如你的代码里,term()读了一个非*//的字符,就用unget()放回去留给后续逻辑处理;factor()里读了数字的第一个字符后,放回去再完整读取整个浮点数。

下面是两种可行的Java替代方案:

方案1:使用PushbackReader(模拟流回退)

Java的PushbackReader类支持unread()方法,功能和C的unget()完全一致,可以把字符推回到输入流中。以下是对应原C代码的Java实现:

import java.io.IOException;
import java.io.PushbackReader;
import java.io.StringReader;

public class ExpressionParser {
    private final PushbackReader reader;

    public ExpressionParser(String input) {
        this.reader = new PushbackReader(new StringReader(input));
    }

    // 读取下一个字符(对应原C++的token())
    private char token() throws IOException {
        int ch = reader.read();
        if (ch == -1) {
            throw new RuntimeException("Unexpected end of input");
        }
        return (char) ch;
    }

    // 回退字符(对应C++的unget())
    private void unget(char ch) throws IOException {
        reader.unread(ch);
    }

    public double factor() throws IOException {
        double val = 0;
        char ch = token();
        if (ch == '(') {
            val = expression();
            ch = token();
            if (ch != ')') {
                throw new RuntimeException("Expected ')', got: " + ch);
            }
        } else if (Character.isDigit(ch)) {
            unget(ch); // 把数字首字符放回流
            // 读取完整的数字字符串
            StringBuilder numStr = new StringBuilder();
            int nextCh;
            while ((nextCh = reader.read()) != -1) {
                char c = (char) nextCh;
                if (Character.isDigit(c) || c == '.') {
                    numStr.append(c);
                } else {
                    unget(c); // 把非数字字符放回
                    break;
                }
            }
            val = Double.parseDouble(numStr.toString());
        } else {
            throw new RuntimeException("Unexpected character: " + ch);
        }
        return val;
    }

    public double term() throws IOException {
        double val = factor();
        char ch = token();
        if (ch == '*' || ch == '/') {
            double b = term();
            val = ch == '*' ? val * b : val / b;
        } else {
            unget(ch); // 放回非操作符字符
        }
        return val;
    }

    public double expression() throws IOException {
        double val = term();
        char ch = token();
        if (ch == '+' || ch == '-') {
            double b = expression();
            val = ch == '+' ? val + b : val - b;
        } else {
            unget(ch); // 放回非操作符字符
        }
        return val;
    }

    public static void main(String[] args) throws IOException {
        ExpressionParser parser = new ExpressionParser("(5+6-(6*2)/3)");
        System.out.println(parser.expression()); // 输出7.0
    }
}

方案2:字符数组+指针(更适合字符串输入)

如果你的输入是字符串而非流,更简单的方式是把整个输入转成字符数组,用一个指针记录当前读取位置,“回退”操作直接把指针减1即可,完全不需要IO处理:

public class ExpressionParser {
    private final char[] input;
    private int pos = 0;

    public ExpressionParser(String input) {
        this.input = input.toCharArray();
    }

    // 读取下一个字符
    private char token() {
        if (pos >= input.length) {
            throw new RuntimeException("Unexpected end of input");
        }
        return input[pos++];
    }

    // 回退操作(指针减1)
    private void unget() {
        if (pos > 0) {
            pos--;
        }
    }

    public double factor() {
        double val = 0;
        char ch = token();
        if (ch == '(') {
            val = expression();
            ch = token();
            if (ch != ')') {
                throw new RuntimeException("Expected ')', got: " + ch);
            }
        } else if (Character.isDigit(ch)) {
            unget(); // 指针回退,重新读取完整数字
            StringBuilder numStr = new StringBuilder();
            while (pos < input.length && (Character.isDigit(input[pos]) || input[pos] == '.')) {
                numStr.append(input[pos++]);
            }
            val = Double.parseDouble(numStr.toString());
        } else {
            throw new RuntimeException("Unexpected character: " + ch);
        }
        return val;
    }

    public double term() {
        double val = factor();
        char ch = token();
        if (ch == '*' || ch == '/') {
            double b = term();
            val = ch == '*' ? val * b : val / b;
        } else {
            unget(); // 指针回退
        }
        return val;
    }

    public double expression() {
        double val = term();
        char ch = token();
        if (ch == '+' || ch == '-') {
            double b = expression();
            val = ch == '+' ? val + b : val - b;
        } else {
            unget(); // 指针回退
        }
        return val;
    }

    public static void main(String[] args) {
        ExpressionParser parser = new ExpressionParser("(5+6-(6*2)/3)");
        System.out.println(parser.expression()); // 输出7.0
    }
}

方案选择建议

  • 如果输入来自文件/网络流,用PushbackReader更合适,能直接处理流输入;
  • 如果输入是字符串(比如表达式解析场景),字符数组+指针的方式更高效,还能避免IO异常处理,代码更简洁。

内容的提问来源于stack exchange,提问作者Dihan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:18:30