为什么我的方法在 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 和换行符。
如果您想将输入视为 个字符 ,而不是 个字节 ,您应该创建一个 BufferedReader
或Scanner
得到 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 中通过按回车键输入的最后一个字符),在方法执行时为您留下一个新的缓冲区又被召唤了。
我开始学习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 和换行符。
如果您想将输入视为 个字符 ,而不是 个字节 ,您应该创建一个 BufferedReader
或Scanner
得到 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 中通过按回车键输入的最后一个字符),在方法执行时为您留下一个新的缓冲区又被召唤了。