System.in.read()输入单个字符返回3次?Java循环异常问题咨询
问题:输入单个字符后for循环多次执行的原因
我正在学习《Java: 从入门到精通》(原书名Java: A Beginner's Guide)一书,书中讲解for循环时给出了这段包含用户输入的代码:
class ForTest { public static void main(String[] args) throws java.io.IOException { int i; System.out.println("Press S to stop."); for(i = 0; (char) System.in.read() != 'S'; i++) System.out.println("Pass #" + i); } }
执行这段代码后,输出和预期不符:输入单个字符并按下回车,程序会打印三次Pass #而非一次。以下是输出示例:
a Pass #0 Pass #1 Pass #2 w Pass #3 Pass #4 Pass #5 1 Pass #6 Pass #7 Pass #8 2 Pass #9 Pass #10 Pass #11
原因解析
这是因为你按下回车时,输入流里不止有你输入的目标字符,还有换行相关的控制字符:Windows系统中,回车会生成\r(回车符)和\n(换行符)两个字符;Linux/macOS中则是\n。而System.in.read()是逐个字节读取输入的,每次调用会读取一个字符,这些控制字符都会被当作循环判断的输入。
拿输入a并回车的场景举例:
- 输入流里实际包含三个字符:
a、\r、\n - 循环条件每次都会调用
System.in.read()读取一个字符:- 第一次读取
a,不等于S,执行循环,打印Pass #0 - 第二次读取
\r,不等于S,执行循环,打印Pass #1 - 第三次读取
\n,不等于S,执行循环,打印Pass #2
- 第一次读取
- 直到输入流里的字符全部读完,程序才会等待下一次输入,所以每次输入字符加回车会触发三次循环。
解决方法
如果想让输入一个字符只触发一次循环,可以改用Scanner类来读取完整的输入行,避免逐个字节读取控制字符的问题:
import java.util.Scanner; class ForTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int i; System.out.println("Press S to stop."); for(i = 0; !scanner.nextLine().trim().equals("S"); i++) System.out.println("Pass #" + i); scanner.close(); } }
这里用scanner.nextLine()读取整行输入,trim()可以去掉输入前后的空白字符(包括回车换行),只有当输入的内容是S时才会终止循环。
内容的提问来源于stack exchange,提问作者Guilherme
相关产品推荐
相关产品推荐

