ACM模式下处理Java的输入
0. 前言
在力扣上刷题的时候不用考虑输入输出的问题,只需要根据所给函数框架写中间逻辑代码,但是很多大厂的笔试都是采用的ACM模式,即函数的输入是从控制台键入的几行数据,而输出是直接将结果打印到控制台。
输入调用的是import java.util.Scanner;
,注意Scanner是util包下的!!输入的处理也可以说是Scanner的用法,现在将一些常见的输入进行总结。
1. 单个输入
有的函数输入很简单,就是一个数,或者一个字符串,或者一行数中间用空格隔开,这种输入很简单,处理方法如下。
- 输入是一个数
import java.util.Scanner;
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取输入的一个整型
int n = sc.nextInt();
// 如果输入的是double类型
//double d = sc.nextDouble();
System.out.println(n);
}
}
- 输入的是一个字符串
import java.util.Scanner;
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 如果输入的是一个字符串
String s = sc.nextLine(); // 读取的是一整行
System.out.println(s);
}
}
2. 一行输入
如果输入的是一行数据,中间用空格隔开,比如输入的是2 3 4
import java.util.Scanner;
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n1 = sc.nextInt(); // 接收第1个数
int n2 = sc.nextInt(); // 接收第2个数
int n3 = sc.nextInt(); // 接收第3个数
}
}
3. 多行输入
多行输入是最常见的。
- 一共输入两行,第一行表示第二行有多少个数,比如第一行为4,第二行为0 2 3 4。根据题意如果需要用一个一维数组来接收第二行的输入,代码如下:
import java.util.Scanner;
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 第一行的数表示第二行有多少个数,即数组的长度
int n = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
}
}
- 输入多行,需要用2维数组接收,比如:
3
1 2
3 5
6 7
第一行3表示下面有3行输入,每行有2个数,我们要用二维数组装下面3行的数,代码如下:
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] nums = new int[n][2];
for (int i = 0; i < n; i++) {
nums[i][0] = sc.nextInt();
nums[i][1] = sc.nextInt();
}
// 自己验证一下对不对
for (int i = 0; i < n; i++) {
System.out.println(nums[i][0]+","+nums[i][1]);
}
}
}
注意自己在验证的时候,分隔号一定要用双引号隔开,单引号字符会参与计算。
- 输入多行字符串,比如输入为:
3
sadfasdgfd
dsgfshgf
dsfasd
第一行表示下面有3行字符串需要接收,后面3行就是对应的字符串,方法与上面类似:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class testStrings {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
// 假设用list来接收
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add(sc.next());
}
// 检查对不对
for (int i = 0; i < n; i++) {
System.out.println(list.get(i));
}
}
}
3. 解析逗号分隔符的字符串
有时候输入不是空格分隔,而是逗号分割的,比如输入的是1,2,3,4,5,并假设我们需要用数组接收,可以这么操作:
import java.util.Scanner;
public class test{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//以字符串形式作为输入
String str = sc.next();
//通过分隔符将其转为字符串数组
String[] arr = str.split(",");
//初始化一个整数数组
int[] nums = new int[arr.length];
//给整数数组赋值
for (int j = 0; j < nums.length; j++) {
nums[j] = Integer.parseInt(arr[j]);
}
}
}
4. 一个非常重要的容易出错的敌方
今天发现了一个很容易出错的输入。假如输入是:
3
a 10 1 2
b 10 2
c 10 3
第一行是是数字N,表示下面有N行输入,下面的N行有字母,也有数字,字母只是标识符,不参与运算,数字的个数不固定,每一行的数字需要用List存储下来,最后将每一行的List放入一个大的List中。
虽然挺起来很扯淡,字母没用输入干嘛?但有的题目就是这样的。
有了上面的基础,有的同学(比如我)就理所当然的写下了如下接收代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i < n; i++) {
List<Integer> list = new ArrayList<>();
String[] inputs = sc.nextLine().split(" ");
for (int j = 1; j < inputs.length; j++) {
list.add(Integer.valueOf(inputs[j]));
}
adj.add(list);
}
}
}
注意:
- 如果写成上面的代码,adj的第一个元素是一个空ArrayList,输入的最后一组数据没有接收到;
- 原因是当我们执行
int n = sc.nextInt();
后,光标还停留在第一行,下面就直接执行sc.nextLine()
来接收输入了,这样接收的第一行N后面的空字符串;
所以有两种方法可以解决这个问题,一是在int n = sc.nextInt();
后添加sc.nextLine();
直接换行,二是将接收N的代码改为int n = Integer.valueOf(sc.nextLine())
即可。修改后代码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 方法一
int n = sc.nextInt();
sc.nextLine();
// 方法二:
// int n = Integer.valueOf(sc.nextLine());
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i < n; i++) {
List<Integer> list = new ArrayList<>();
String[] inputs = sc.nextLine().split(" ");
for (int j = 1; j < inputs.length; j++) {
list.add(Integer.valueOf(inputs[j]));
}
adj.add(list);
}
}
}
5. 其他
- 关于
while(sc.hasNext()) {}
我看很多人输入直接用while(sc.hasNext()) {}
包括起来,这段代码意思是一直等待输入,除非终止程序。其实应该根据题意进行判断:一般情况下,如果输出是单个,就不用while包括;如果输入是多个,多个输入都需要经过相同的逻辑判断然后在输出,这时候就必须用while(sc.hasNext()) {}
包括起来。
注意:我说的是多个输入,而不是多行输入!
举个例子:
给定一个日期,输出这个日期是该年的第几天。
Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成:
1985/1/20
2006/3/12
题解参考如下:
import java.util.Scanner;
public class Solution{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] dd = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
while (sc.hasNext()) {
int days = 0;
String str = sc.nextLine();
String[] date = str.split("/");
int y = Integer.parseInt(date[0]);
int m = Integer.parseInt(date[1]);
int d = Integer.parseInt(date[2]);
if ((y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) && m > 2)
days++;
days += d;
for (int i = 0; i < m; i++) {
days += dd[i];
}
System.out.println(days);
}
}
}
综上,如果题目中没有明说一次给几个输入,为了保险可以直接无脑用while(sc.hasNext()) {}
包括起来。
一般大厂笔试的输出比较简单,没有需要format的地方,就不总结输出了。其他的遇到再补充。