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的地方,就不总结输出了。其他的遇到再补充。

  • 13
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值