为什么我的方法在 System.in.read() 循环后被调用 3 次

Why my method being called 3 times after System.in.read() in loop

我开始学习Java,写了一些很简单的东西,但是有一点我不明白:

public static void main(String[] args) throws java.io.IOException
{
    char ch;

    do 
    {
        System.out.println("Quess the letter");
        ch = (char) System.in.read();
    }
    while (ch != 'q');
}

为什么 System.out.println 给出错误答案后打印 3 次 "Quess the letter"。在给出任何答案之前,字符串只打印一次。

提前致谢

因为当您打印 char 并按 Enter 时,您会生成 3 个符号(在 Windows 上):字符、回车符 return 和换行符:

q\r\n

您可以在此处找到更多详细信息:http://en.wikipedia.org/wiki/Newline

对于您的任务,您可能需要使用更高级别 API,例如Scanner:

    Scanner scanner = new Scanner(System.in);
    do {
        System.out.println("Guess the letter");
        ch = scanner.nextLine().charAt(0);
    } while (ch != 'q');

直接使用System.in可能是错误的做法。如果您的字符从 q 更改为俄语、阿拉伯语或中文,您会看到。只读取一个字节永远不会匹配它。你很幸运,从控制台读取的 UTF-8 字节与纯英文字符的字符代码匹配。

您这样做的方式是将输入视为字节流。然后,正如@Sergey Grinev 所说,您会得到三个字符 - 您输入的实际字符,以及通过按 Enter 产生的回车 return 和换行符。

如果您想将输入视为 个字符 ,而不是 个字节 ,您应该创建一个 BufferedReaderScanner 得到 System.in 的支持。然后你可以读一整行,它会为你处理回车return和换行符。

要使用 BufferedReader,您需要执行以下操作:

BufferedReader reader = new BufferedReader( InputStreamReader( System.in ) );

然后你可以使用:

String userInput = reader.readLine();

要使用 Scanner,您需要执行以下操作:

Scanner scanner = new Scanner( System.in );

然后你可以使用:

String userInput = scanner.nextLine();

在这两种情况下,结果都是 String,而不是 char,因此您应该小心 - 不要使用 == 但使用 equals()。或者确保其长度大于 1 并使用 charAt(0).

获取其第一个字符

如前所述,初始读取命令接收 3 个字符并将它们保存在缓冲区中。

下次读取命令出现时,它会先检查缓冲区,然后再等待键盘输入。在按回车键之前尝试输入多个字母 - 无论您输入多少个字符 + 2,您的方法都应该被调用。

更简单的修复:

//add char 'ignore' variable to the char declaration
char ch ignore;

//add this do while loop after the "ch = (char) System.in.read();" line
do{
    ignore = (char) System.in.read();
} while (ignore != '\n');

这种方式 'ignore' 将在缓冲区中循环,直到遇到缓冲区中的换行符(在 Windows 中通过按回车键输入的最后一个字符),在方法执行时为您留下一个新的缓冲区又被召唤了。