我正在构建一个语言解释器,需要有两个函数,一个用于输入整数,另一个用于输入字符(来自 System.in)。例如输入整数-字符-整数-字符-字符-字符来自
123 C
456
DEF
应给出
123
、C
、456
、D
、E
和 F
。
在我当前的实现中,我可以获取
123
、C
、456
、D
(通过耗尽当前输入行)或获取 123
、C
、456
、E
, F
(跳过行首的任何字符)。
我的代码是:
class Variable extends Var {
private static Scanner scanner = new Scanner(System.in);
private static String buffer = ""; // Buffer to hold unprocessed characters
private static int bufferIndex = 0; // Index to track the next character in the buffer
private String name;
public Variable(String name) {
this.name = name;
}
public String getName(HashMap<String, Integer> values) {
return name;
}
public int evaluate(HashMap<String, Integer> values) {
if (name.equals("read")) {
return scanner.nextInt();
}
if (name.equals("get")) {
// Refill buffer if empty or fully processed
while (bufferIndex >= buffer.length()) {
buffer = scanner.nextLine();
bufferIndex = 0; // Reset the index for the new buffer
}
// Return the ASCII value of the next character in the buffer
return (int) buffer.charAt(bufferIndex++);
}
return values.getOrDefault(name, 0);
}
}
扫描仪是最不适合这项工作的工具。或者,至少,你使用它的方式。
Scanner 是将输入分离为标记并返回这些标记的东西。标记被定义为“分隔符之间的内容”,分隔符默认设置为“任意数量的空格”。
你想要的是一个时髦的分隔符:“2个字符之间任意数量的空格,包括根本没有空格,但2个数字之间至少有1个空格”。
这会让你陷入奇特的正则表达式中,除非你非常熟悉它们,否则它们是不可读的。
如果你跳过所有这些并找到另一种方法来做到这一点,你会学到更多。例如,只抓取单个字符。只有当你获取的字符是数字并且前一个字符也是数字时,才将它们组合成一个新数字,否则,你得到了一个令牌。
忘记
Scanner
,无论如何,它从来都不是用于键盘输入的。
class MyApp {
public static void main(String[] args) throws IOException {
new MyApp().go();
}
StringBuilder token = new StringBuilder();
void go() throws IOException {
while (true) {
int v = System.in.read();
if (v == -1) {
cycleToken();
return;
}
char w = (char) v;
if (w >= '0' && w <= '9') {
token.append(w);
} else {
cycleToken();
token.append(w);
cycleToken();
}
}
}
void cycleToken() {
String z = token.toString().trim();
if (!z.isEmpty()) System.out.println("TOKEN: " + z);
token.setLength(0);
}
}
StringBuilder
是一个可变字符串。我们在这里需要它来添加数字;在看到非数字或输入结束之前,我们不知道何时“完成”数字。