【Java】Scanner 的用法:单行/多行输入
本文较大程度参考以下博客,并根据自己本身需求与理解撰写。
https://blog.csdn.net/qq_34826261/article/details/97616358
https://blog.csdn.net/qq_40164190/article/details/81917208
一、Java Scanner类
Scanner类简介
Java 5添加了java.util.Scanner类,这是一个用于扫描输入文本的新的实用程序。它是以前的StringTokenizer和Matcher类之间的某种结合。由于任何数据都必须通过同一模式的捕获组检索或通过使用一个索引来检索文本的各个部分。于是可以结合使用正则表达式和从输入流中检索特定类型数据项的方法。这样,除了能使用正则表达式之外,Scanner类还可以任意地对字符串和基本类型(如int和double)的数据进行分析。借助于Scanner,可以针对任何要处理的文本内容编写自定义的语法分析器。
Scanner类的常用方法
其实上图的意思就是,比如:nextlnt():只读取int值,就是只能读取整数类型的数据,如果输入了非整型的数据(浮点型字符串等)就会报错。
nextFloat()、nextDouble()这些也是以此类推,只能读取符合该类型的数据。
代码:
public class Text {
public static void main(String []args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个字符串(中间能加空格或符号)");
String a = input.nextLine();
System.out.println("请输入一个字符串(中间不能加空格或符号)");
String b = input.next();
System.out.println("请输入一个整数");
int c;
c = input.nextInt();
System.out.println("请输入一个double类型的小数");
double d = input.nextDouble();
System.out.println("请输入一个float类型的小数");
float f = input.nextFloat();
System.out.println("按顺序输出abcdf的值:");
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
System.out.println(f);
}
}
运行结果:
请输入一个字符串(中间能加空格或符号)
我爱祖国!
请输入一个字符串(中间不能加空格或符号)
ILoveChina
请输入一个整数
520
请输入一个double类型的小数
12.26e3
请输入一个float类型的小数
3.1415926
按顺序输出abcdf的值:
我爱祖国!
ILoveChina
520
12260.0
3.1415925
Scanner类的常用方法2
代码演示:
public class inputInformation {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in); //构造Scanner类的对象scan,接收从控制台输入的信息
System.out.println("请输入你的姓名");
String name = scan.nextLine();//接收一个字符串,可以加除Enter以外的所有符号,包括空格和Tab
System.out.println("请输入你的ID");
String ID ;
while(scan.hasNextLine()) {// hasNextLine()方法判断当前是否有输入,当键盘有输入后执行循环
if(scan.hasNextInt()) {// 判断输入的值是否为整数类型,当为整数类型时执行循环
ID = scan.nextLine();
System.out.println("你输入的姓名为:"+name);
System.out.println("你输入的ID为:"+ID);
break;
}else {
System.out.println("请输入数字哦!");
ID = scan.nextLine();
continue;
}
}
}
}
运行结果如下:
请输入你的姓名
华为
请输入你的ID
q764323221
请输入数字哦!
764323221
Scanner.close()方法的作用是关闭输入的流,释放内存。Scanner 类实例化的时候需要一个InputStream流作为参数,Scanner的close就是关闭InputStream流的,一般是IO流或scanner方法使用完后就可以调用close()方法释放内存了,如果你是小程序可以不用使用.close方法,这个不影响,但如果项目很大的时候就肯定要用了,所以建议养成良好的习惯。
二、Java的Scanner用法,主要用于算法笔试时的控制台输入
1 问题:解决这种情况下的Scanner输入:单行,多行,数值,字符串
平时写程序一般不用Scanner,线上笔试的时候,各大公司热衷于Scanner输入。
平时用LeetCode刷题也不会用到,结果多次在笔试时候卡在Scanner,特来总结一波。
2 单行输入多个参数
在一行输入多个参数
以空格(也可用其他的符号,不重要)为分割。
// 输入如下
ABB CCC DDD EEE 123 435
程序如下:
import java.util.Arrays;
import java.util.Scanner;
public class myScanner {
Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("输入:");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine(); // 读取一行
System.out.println("输出:");
System.out.println(str);
String[] strIn = str.trim().split(" "); // 以空格分割
System.out.println(Arrays.toString(strIn));
}
}
读出来的只能是字符串,如果想全部为数字,需要将读出来的字符串强行转换为数字(parseInt、parseLong等),运行示例如下:
3 多行输入多个参数,每行参数个数不定
多行输入元素,其中第一行几个数字表示下面几行的个数,每行可能输入不等数量的参数
以三行输入为例,第一行输入两个数字m,n,分别表示数组num1和num2的长度,第二行和第三行输入num1和num2的元素,以空格分隔。
// 输入如下
3 4
10 2 3
11 4 5 6
程序如下:
import java.util.Arrays;
import java.util.Scanner;
public class Scanner2 {
public static void main(String[] args) {
System.out.println("输入:");
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int t = sc.nextInt();
// 换成其他数据类型也一样,其他数值类型就修改int跟nextInt就可以了,
//String就把nextInt()换成next()
System.out.println(m);
System.out.println(n);
System.out.println(t);
int[] num1 = new int[n];
int[] num2 = new int[t];
for(int i = 0; i < n; i ++) {
num1[i] = sc.nextInt(); // 一个一个读取
}
System.out.println(Arrays.toString(num1));
for(int i = 0; i < t; i ++) {
num2[i] = sc.nextInt();
}
System.out.println(Arrays.toString(num2));
}
}
运行示例:
换成其他数据类型也一样,其他数值类型就修改int跟nextInt就可以了,String就把nextInt()换成next()
三、自己的理解:
next()和nextLine()的区别
next():只读取输入直到空格。它不能读两个由空格或符号隔开的单词。此外,next()在读取输入后将光标放在同一行中。(next()只读空格之前的数据,并且光标指向本行)
nextLine():读取输入,包括单词之间的空格和除回车以外的所有符号(即。它读到行尾)。读取输入后,nextLine()将光标定位在下一行。
public class MyScanner {
public static void main(String[] args) {
System.out.println("输入:");
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
System.out.println("m: "+m);
//sc.nextLine(); // 很重要,跳到第二行
// 若直接确定行数,注释掉上面两行,加入下面一行
// int m = 3;
String[] strArr = new String[m];
// 从第二行开始读取
for(int i = 0; i < m; i++) {
strArr[i] = sc.nextLine();
}
System.out.println("输出:");
System.out.println(Arrays.toString(strArr));
ArrayList<String[]> strToOne = new ArrayList<String[]>();
for(int i = 0; i < m; i ++) {
String[] tmp = strArr[i].trim().split(" ");
strToOne.add(tmp);
}
System.out.println(strToOne);
// 形象点显示
System.out.print("[");
for(int i = 0; i < strToOne.size(); i++) {
System.out.print(Arrays.toString(strToOne.get(i)));
if(i != strToOne.size()-1)
System.out.print(", ");
}
System.out.print("]");
}
}
输出为:
输入为字符串:
// 输入如下
3 4
AA bcd 123 54
AA BB
A B C
添加了 sc.nextLine(); 代码后的变化:
程序如下:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class myScanner {
public static void main(String[] args) {
System.out.println("输入:");
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
sc.nextLine(); // 很重要,跳到第二行
// 若直接确定行数,注释掉上面两行,加入下面一行
// int m = 3;
String[] strArr = new String[m];
// 从第二行开始读取
for(int i = 0; i < m; i++) {
strArr[i] = sc.nextLine();
}
System.out.println("输出:");
System.out.println(Arrays.toString(strArr));
ArrayList<String[]> strToOne = new ArrayList<String[]>();
for(int i = 0; i < m; i ++) {
String[] tmp = strArr[i].trim().split(" ");
strToOne.add(tmp);
}
System.out.println(strToOne);
// 形象点显示
System.out.print("[");
for(int i = 0; i < strToOne.size(); i++) {
System.out.print(Arrays.toString(strToOne.get(i)));
if(i != strToOne.size()-1)
System.out.print(", ");
}
System.out.print("]");
}
}
运行结果如下:
从上述两份1代码比较可得,第一行输入 “3 4 5”,添加 sc.nextLine()
后,“4 5” 未赋值给变量。
字符串以空格为分隔符赋值
import java.util.Arrays;
import java.util.Scanner;
public class Myscanner3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("输入:");
Scanner sc = new Scanner(System.in);
String nextLine = sc.nextLine();
String[] str = nextLine.trim().split(" ");
System.out.println(Arrays.toString(str));
int[] num = new int[str.length];
for (int i = 0; i < str.length; i++) {
num[i]=Integer.parseInt(str[i]);
}
System.out.println(Arrays.toString(num));
}
}
效果展示:
这个主要是用于【输入多行,而每行的输入个数无法确定的情况】
而且还可以根据需要决定是否转化为数值型变量
总结:
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
String str = scanner.nextLine();
System.out.println(m);
System.out.println("*"+str+"*");
// 输入:123 aaa
// 第一行输出123
// 第二行输出* aaa*
// 输入123
// 第一行输出123
// 第二行输出**
// 输入123
// 第一行输出123
// 第二行输出* *
- .nextXxx() 方法遇到分隔符的时候,光标仍停留在这一行。而 .nextLine() 方法遇到分隔符的时候却会换行
- 几乎除了 .nextLine() 之外,所有的区分分隔符都是 空格 " "或者【回车】;
- 【在同一行输入中】 可以使用多个除了 .nextLine() 之外的方法。分割划分变量很简单,遇到空格就可以得出一个变量;在上例三行参数输入的例子中,其实使用空格为分隔符,可以给所有的参数赋值;
- 而对于 .nextLine() 方法,则是【一遇到回车就立马换行】,顺便保存点东西
- 那保存的是什么呢? 可能在同一行的前面还有多个别的 .nextXxx() 方法。而着多个方法得到的变量的子后一个变量一定是以空格符或者回车区分的。 那么此时, .nextLine()方法则会记录下最后一个变量的最后一个字符的之后的所有字符汇总成一个变量(当然,不包括回车)
然后这所有的字符又可以赋值给一个字符串变量
说这么多就是为了说明一点:只调用 .nextLine() 方法,而不选择赋值给变量的话,则就是为了【单纯的换行而已!】