一. 发现问题
今天在洛谷刷题,就发现这字符串死活输不进去,然后就有了今天的文章。先看下面这个问题。
1. sc.nextLine()
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
String str2 = sc.nextLine();
System.out.println(str1);
System.out.println(str2);
}
}
很基础,对吧,但是结果很奇葩,我们来看看执行的结果。

这里我输入进去了字符串“1”和“2”,打印的时候,只打印了“1”,为什么呢,让我们debug一下。看到了如下的结果:

str2并没有读进去该有的“2”。猜想:如果是不是读进去了一个别的字符?我们修改一下代码,如下:
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
sc.nextLine();
String str2 = sc.nextLine();
System.out.println(str1);
System.out.println(str2);
}
}
博主这里增加了一个sc.nextLine(),用来读取别的字符

这次str2保存了正确的值,并成功打印出来了。
2. sc.nextInt()
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
String str = sc.nextLine();
System.out.println(num);
System.out.println(str);
}
}
感觉没啥毛病本来,结果运行,是个这?如下图:

就让我输入了一个num,后面我还没来得及输入,就结束了。让我们debug一下,如下图:

和上面的情况一样,str还是没有输进去,空值一个。那和上面一样,我们也加一个sc.nextLine()看看结果怎么样:
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
sc.nextLine();
String str = sc.nextLine();
System.out.println(num);
System.out.println(str);
}
}
运行结果如下:

这回让我输入str了,但是好像还是没保存下来,这怎么有点像上面sc,nextLine()所出现的情况了。。。debug again:

还是没读进去,好吧,那我们再加一个sc.nextLine()试试,代码如下:
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
sc.nextLine();
sc.nextLine();
String str = sc.nextLine();
System.out.println(num);
System.out.println(str);
}
}
这次运行成功了,如下图:

二. 分析问题
为什么会出现这个样子呢,查了查资料发现:
键盘上敲了回车键之后,其实是向程序送入了两个字符---------‘\r‘ 和 ‘\n’
- sc.nextInt(),输入完数字后,‘\r‘ 和 ’\n’ 都留在了缓冲区。
- sc.nextInt()之后需要两个nextLine()来处理别的字符。
- 而sc.nextLine(),输入完字符串之后,只有 ‘\n’ 留在了缓冲区当中。
- sc.nextLine()之后,需要一个nextLine()来处理其他字符。
三. 总结
- Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<回车><换行>”,即“ \r\n”;Mac系统里,每行结尾是“<回车>”,即“\r”
- ‘\r’表示回车(carriage return)即回到行首,并没有包含换行的动作;’\n’表示换行(line feed)即移动到新的一行(下一行)
- nextInt()和next()、nextFloat()、nextDouble()都是只读取有效字符的,不会读取空格键、Tab键和回车键。
- 当它在输入有效字符前碰到这些无效字符时会自动跳过,在碰到时有效字符后便结束读取,并把无效字符留在缓冲区中。
- nextLine()除了回车啥都能读取,也就是碰到回车时结束读取,但会把回车留在缓冲区。
参考:
https://blog.csdn.net/cnds123/article/details/126389380
https://blog.csdn.net/weixin_55000908/article/details/123888389
https://blog.csdn.net/m0_63162560/article/details/126211023
四. 新的问题
1.
package 洛谷;
import java.util.*;
public class Test {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要打印的内容:");
String info1 = sc.nextLine();
System.out.println("键盘输入的数字数据是:"+info1);
String info2 = sc.nextLine();
String info3 = sc.nextLine();
System.out.println("键盘输入的字符串数据是:"+info2);
System.out.println("键盘输入的数字数据是:"+info3);
}
}
结果如下:

这里info2居然读进去了????难倒System.out.println();有清空暂存区的效果?博主读了半天源码,没看懂。。。可能是太菜了
2.

还有这样一段代码,这里加了sc.nextLine(),反而会等待输入。。让人百思不得其解。
如果有大佬知道,请不吝赐教,抱拳了!
文章讨论了在使用Java的Scanner类处理用户输入时遇到的问题,主要集中在sc.nextLine()和sc.nextInt()方法的使用。当使用nextInt()后,需要额外的nextLine()来清除缓冲区中的回车符。同样,处理字符串输入时也可能需要多个nextLine()。文章提供了示例代码和调试结果,分析了Unix、Windows和Mac系统中换行符的差异,并提出了新的问题关于System.out.println()是否影响缓冲区状态。
5457

被折叠的 条评论
为什么被折叠?



