刷题中的输入输出汇总

前记

因为还要备战第二次蓝桥杯和为了以后的算法笔试,所以我准备汇总一下刷题过程中遇到的输入和输出情况,可能这篇文章会随着我刷题量而不断更新。



前置知识

java常用的输入方式有四种(System.in,Scanner,InputStreamReader,BufferesReader),这里一般我们常用的是Scanner或者BufferesReader,我只介绍这两种。

Scanner

java.util.Scanner是Java5的新特征,主要功能是简化文本扫描,这个类最实用的地方表现在获取控制台输入。当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象。如果要获取输入的内容,则只需要调用Scanner的nextLine()方法即可。

Scanner也可以从字符串(Readable)、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段(根据正则分隔式)来扫描整个文本,并对扫描后的结果做想要的处理。

Scanner 类的 nextInt() 方法实际上是从标准输入流中读取文本数据,并尝试将其解析为整数。

控制台扫描:

1
2
3
4
5
6
Scanner in = new Scanner(System.in);
while (true) {
String line = in.nextLine();
if (line.equals("exit")) break; //如果输入为"exit",则退出
System.out.println("输入:" + line);
}

Scanner默认使用空格作为分割符来分隔文本,但允许你指定新的分隔符:

1
2
3
4
5
6
7
8
Scanner sc = new Scanner("123 asdf sd 45 789 sdf asdfl,sdf.sdfl,asdf    ......asdfkl    las");
// 以自己制定方式分割文本,支持正则表达式
//sc.useDelimiter(" |,|\\.");

while (sc.hasNext()) {
System.out.println(sc.next());
//会以空格为间隔依次输出上面的字符串
}

重要api:

1
2
3
4
5
6
7
8
9
10
public Pattern delimiter ()  //返回此 Scanner 当前正在用于匹配分隔符的 Pattern。

public boolean hasNext () //判断扫描器中当前扫描位置后是否还存在下一段。

public boolean hasNextLine () //如果在此扫描器的输入中存在另一行,则返回 true。

public String next () //查找并返回来自此扫描器的下一个完整标记。

public String nextLine () // 此扫描器执行当前行,并返回跳过的输入信息。
public int nextInt () //扫描下一个整数,依次类推还有Double、Floate、Long等

BufferedReader

BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。(通常和InputStreamReader连用,因为输入的数据是字节流,需要InputStreamReader将其转成成字符流)

常用构造:

1
2
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//这行代码创建了一个能够从标准输入读取数据的 BufferedReader 对象,并将其存储在变量 br 中。

对应解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
System.in
//System.in 是 Java 中的一个标准输入流,通常用于从控制台(键盘)读取用户输入。它是一个InputStream 对象,用于读取字节数据。
new InputStreamReader(System.in);
//构造一个InputStreamReader对象这个对象是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
new BufferedReader(new InputStreamReader(System.in));
//构造一个字符流的缓存,里面存放在控制台输入的字节转换后成的字符。
str=bf.readLine();
//从这个缓存中读取一行的内容

//整个这句话拆开来写为:
InputStream in = System.in ;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);


输入

明确数据个数

一维数组

对于样例数据,如果题目要求的处理方式都是一样的,且给定了数据的个数,那么我们就能创建一个一维数组来解决。

示例一:

输入包括两行数据。第一行包含10个100到200之间(包括100和200)的整数(以厘米为单位)分别表示10个苹果到地面的高度,两个相邻的整数之间用一个空格隔开。第二行只包括一个100到120之间(包含100和120)的整数(以厘米为单位),表示陶陶把手伸直的时候能够达到的最大高度。


示例二:

image-20231123204833259

1
2
3
4
5
6
int n = 36;
int[] a = new int[n];

for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}


二维数组

示例一:

对于二维数组,而且样例中没有空格的时候,我们一般可以两层for循环输入,或者一层for循环,将每一行输入转换成一个字符数组。

image-20231123213506775

1
2
3
for (int i = 1; i <= n; i++)
s[i] = (" " + scanner.next()).toCharArray();
//从下标1开始

示例二:

样例中出现空格时候,我们一般用二维数组接收(因为next()不接收空格)即可。

1
2
3
4
5
6
5 6 
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1
2
3
4
5
6
7
        char[][] arr = new char[m][n];
for (int i =0; i < m; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = in.next().charAt(0);
}
}
//或者直接用整数接收,看个人习惯

示例三:

样例没有空格,而且需要查找某一个具体数组值的时候。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Scanner in = new Scanner(System.in);
C = in.nextInt(); //列
R = in.nextInt(); //行
int x=-1;
int y=-1;
in.nextLine(); //吃掉前面输入的回车
for (int i = 0; i < R; i++) {
String line = in.nextLine();
for (int j = 0; j < C; j++) {
arr[i][j] = line.charAt(j);
if(arr[i][j] == 'K'){
x = i;
y = j;
}
}
}


不明确数据个数

在我们不明确输入的行数和个数的时候,经常会用到while循环+hasNext()判断。

直接输入

image-20231123212419425

1
2
3
4
5
6
7
8
9
10
while(sc.hasNext())
{
double N = sc.nextDouble();
int cnt = 0;
while (N >= 1) {
N /= 2;
cnt++;
}
System.out.println(cnt);
}


一维数组

示例一:

image-20231123212801199

1
2
3
while (in.hasNext()) {
String[] a = in.nextLine().split("\\.");
}

示例二:

image-20231123214216775

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while (scanner.hasNext()) {
int n = scanner.nextInt();
scanner.nextLine();

String[] str = new String[10000];
int realCount = 0;

for (int i = 0; i < n; i++) {
str[i] = scanner.nextLine();
realCount++;

if (str[i].equals("stop")) {
realCount--;
break;
}
}
......
}

示例三:

image-20231123234809060

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//方式1:   
Scanner in = new Scanner(System.in);
//将输入的内容添加到list
List<Integer> list = new ArrayList<>();
Scanner sc = new Scanner(in.nextLine()); //输入换行结束,这个Scanner对象是读取in的内容,不是读取键盘了
while (sc.hasNext()) {
int x = sc.nextInt();
list.add(x);
}

//方式2:
Scanner in = new Scanner(System.in);
Scanner sc = new Scanner(in.nextLine()); //输入换行结束,这个Scanner对象是读取in的内容,不是读取键盘了
int[] a = new int[100005];
int n = 0;
while (sc.hasNext()) {
a[n] = sc.nextInt();
n++;
}


//方式3:
Scanner in = new Scanner(System.in);
String[] str = in.nextLine().split(" ");
//输入很细节,不确定数组长度时候使用,因为nextLine()遇到回车退出
int[] a = new int[100005];
for (int i = 0; i < str.length; i++) {
a[i+1]=Integer.parseInt(str[i]);
}
//a[1]=str[0],a[2]=str[1].....

二维数组

示例一:

image-20231129232147258

1
2
3
4
5
6
7
8
9
10
11
6 9 
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
0 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//1. 正常输入
while(true){
n =in.nextInt();
m =in.nextInt();
if(n==0 &&m==0)
break;
for (int i = 0; i < m; i++) {
ct[i] = in.next().toCharArray();
}
}

//2. 输入流输入
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String[] input = reader.readLine().split(" ");
n = Integer.parseInt(input[0]);
m = Integer.parseInt(input[1]);
if (n == 0 && m == 0) break;
for (int i = 0; i < m; i++) {
ct[i] = reader.readLine().toCharArray();
}
}


输出

基本都是难在输入,所以输出部分就没有什么内容…..

多组输入多组输入

这种情况是最常见的,我们只需要不断读取每一行的内容,然后在循环末尾添加打印语句。

1
2
3
4
5
6
7
8
9
10
while(sc.hasNext())
{
double N = sc.nextDouble();
int cnt = 0;
while (N >= 1) {
N /= 2;
cnt++;
}
System.out.println(cnt);
}


参考

java中的四大输入:System.in,Scanner,InputStreamReader,BufferesReader的用法与区别【改】-CSDN博客

BufferedReader(new InputStreamReader(System.in));-CSDN博客