針對OJ的JAVA 輸入(PAT,牛客網,杭電 etc)

spearous發表於2020-12-22

Java的輸入輸出主要是使用Scanner 類來實現的,這包括從鍵盤讀取輸入,從檔案讀取輸入,向螢幕輸出和寫入檔案。另外,為了提高速度,我們還會使用帶緩衝區的讀和寫。

I. java.util.Scanner

1. 讀取鍵盤輸入:

首先必須引入這個包:import java.util.Scanner

然後使用 Scanner sc = new Scanner(System.in) 生成Scanner物件。System.in 在這裡代指標準輸入流,預設定義為鍵盤輸入。也可以傳入一個字串,作為需要Scanner處理的物件。

import java.io.IOException;
import java.util.Scanner;

public class ScannerExample{
    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(System.in);  // 聲稱Scanner物件
        System.out.println("Enter username");

        String userName = sc.nextLine();  // 讀取整行作為輸入,以Enter鍵作為結束符
        System.out.println("Username is: " + userName);  // 輸出讀取的輸入
    }
}

在OJ中,常指定主類為public Main 形式,如PTA, 牛客網等:你需要把上面的"public class ScannerExample" 換為 "public class Main"。另外, OJ還有固定的幾種輸入,比如

a >  多行輸入,每行是一個數字(整數或者浮點數):

Input 輸入資料有多組,每組佔一行,由一個整陣列成。
       Sample Input
       56
       67
      100
      123

import java.io.IOException;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) { //判斷是否結束
            int score = sc.nextInt();
            System.out.println(score);
        }

    }
}

b> 多行輸入,每行是不定數個給定型別的數字

示例: https://ac.nowcoder.com/acm/contest/320/G

輸入資料有多組, 每行表示一組輸入資料。每行不定有n個整數,空格隔開。(1 <= n <= 100)。

1 2 3

4 5

0 0 0 0 0

因為每行數字個數是不定的,所以只能使用while迴圈。我們可以先用Scanner讀取輸入的一行,然後再用另一個Scanner 把每一行分解到每行數字。

import java.io.IOException;
import java.util.Scanner;

public class Main {
   public static void main(String[] args) throws IOException {
        int sum;
        Scanner sc = new Scanner(System.in);

        while (sc.hasNextLine()){
            sum = 0;
            String Line = sc.nextLine();
            Scanner sc2 = new Scanner (Line);
            while (sc2.hasNextInt()){
                int currElement = sc2.nextInt();
                sum = sum + currElement;
            }
            System.out.println(sum);
        }

    }
}

c > 多行輸入,單獨數字的一行,或某行某數字決定了下面將有幾行。

示例: http://acm.hdu.edu.cn/showproblem.php?pid=2017

輸入資料有多行,第一行是一個整數n,表示測試例項的個數,後面跟著n行,每行包括一個由字母和數字組成的字串。

Sample Input

2

asdfasdf123123asdfasdf

asdf111111111asdfasdfasdf

import java.io.IOException;
import java.util.Scanner;


public class Main {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            String str = sc.next();
            System.out.print(str+'\n');
        }
    }
}

也可以使用 n = integer.parseInt(sc.nextLine())  (替換 int n = sc.nextInt())

d >  指定分隔符的數字,字串識別

示例:http://acm.hdu.edu.cn/showproblem.php?pid=2005

輸入資料有多組,每組佔一行,資料格式為YYYY/MM/DD組成,具體參見sample input ,另外,可以向你確保所有的輸入資料是合法的。

1985/1/20

2006/3/12

import java.io.IOException;
import java.util.Scanner;


public class ScannerExampleParseDate {
    public static void main(String[] args) throws IOException {
        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);
        }
    }
}

e> 多行輸入,行內資料型別不全相同,但位置相同

示例:http://acm.hdu.edu.cn/showproblem.php?pid=1170

輸入:Input contains multiple test cases. The first line of the input is a single integer T (0<T<1000) which is the number of test cases. T test cases follow. Each test case contains a char C (+,-,*, /) and two integers A and B(0<A,B<10000).Of course, we all know that A and B are operands and C is an operator.

Sample Input

4

+ 1 2

- 1 2

* 1 2

/ 1 2

import java.io.IOException;
import java.util.Scanner;

public class ScannerExampleVariesTypeInOneLine {
    public static void main(String[] args) throws IOException {
        Scanner sc =new Scanner(System.in);
        int n = sc.nextInt();
        for(int i=0;i<n;i++){
            String op = sc.next();
            int a = sc.nextInt();
            int b = sc.nextInt();
            if(op.charAt(0)=='+'){
                System.out.println(a+b);
            }else if(op.charAt(0)=='-'){
                System.out.println(a-b);
            }else if(op.charAt(0)=='*'){
                System.out.println(a*b);
            }else if(op.charAt(0)=='/'){
                if(a % b == 0) System.out.println(a / b);
                else System.out.format("%.2f", (a / (1.0*b))).println();
            }
        }
    }

}

f> 建立陣列或者動態擴增ArrayList來儲存讀入的資料

當給定大小時,可以直接建立陣列

int n = sc.nextInt();
int[] arr = new int[n];//動態建立大小為n的陣列
for(int i = 0; i < n; i++){
    arr[i] = sc.nextInt();
}

當給定的大小不定時,使用ArrayList動態擴增

List<String> strList = new ArrayList<String>();//Java 7中可以List<String> strList = new ArrayList<>();
while(sc.hasNextLine()){
    strList.add(sc.nextLine());
}

//遍歷輸出列表中的內容
for (int i = 0; i < strList.size(); i++) {
    String str = strList.get(i);
    System.out.println(str);
}
//或者
for(String e: strList){
    System.out.println(e);
}

 

2. 讀取檔案

Scanner 類同樣可以讀取檔案,只是這時候需要傳入一個檔案物件即可。基本格式為:

import java.io.File
import java.util.Scanner
import java.io.IOException

省略其他程式碼

File infile = new File(src/resource/test.txt);
Scanner sc = new Scanner(infile);


省略其他程式碼

示例中使用的是在java 工程中的相對路徑:

這裡寫圖片描述

我們也可以使用絕對路徑:

File infile = new File("C:\project\infile.txt");

讀取檔案如果有固定格式,那麼按照給定格式解析即可。否則應該一次一行的讀取,使用nextLine()方法。

示例:從一個檔案中讀取資料,需要將奇數行、偶數行的資料分別存放到不同的陣列中,而且,奇數行獲取偶數行中每個資料中間空格數不同。

資料格式:

23 23           32     32 43         21 23        3   43

 

2   43  23 1 2            3

 

9              8 1       2  3

3 4 88 99          99

import java.io.File;
import java.util.Scanner;

// 相對檔案讀取處理
public class FileReader {

    public static void main(String[] args) throws Exception {
        fileReader("src/resource/test.txt");
    }

    public static void fileReader(String fileName) throws Exception {

        File file = new File(fileName);
        Scanner sc = new Scanner(file);

        int rows = 1; // 記錄行數

        String[] odd = new String[40]; // 奇數行資料
        String[] even = new String[40]; // 偶數行資料
        while (sc.hasNextLine()) {
            if ((rows % 2) == 1) { // 奇數行
                odd = sc.nextLine()***.split("\\s{1,}")***;  // split("\\2{1,}");不論字元中間有多少個空格都當作一個空格處理
                System.out.println("奇數行:" + rows);
                for (int i = 0; i < odd.length; i++) {
                    System.out.println(odd[i]);
                }
            } else if ((rows % 2) == 0) { // 偶數行
                even = sc.nextLine().***split("\\s{1,}***");
                System.out.println("偶數行:" + rows);
                for (int i = 0; i < even.length; i++) {
                    System.out.println(even[i]);
                }
            }
            rows++;
        }
        sc.close();
    }

}

 

II. 使用緩衝區讀: BufferedReader/ BufferedWriter

import java.io.BufferedReader;
import java.io.Reader;

public class Main {
    public static void main(String[] args) throws Exception {
        char c ;
        BufferedReader bd = new BufferedReader(new InputStreamReader(System.in));

        //read(),讀入一個字元
        System.out.println("input a char,end with 'e'");
        do {
            c = (char)bd.read() ;
            System.out.println(c);
        }while(c != 'e') ;

        //readLine(),讀入每行的文字資料(包括空格)
        String str=null ;
        System.out.println("string end with 'end'");
        do {
            str = bd.readLine() ;
            System.out.println(str);
        }while(!str.equals("end")) ;
    } 
}

 

III 最快的讀法: java.util.StringTokenizer / java.io.StreamTokenizer

 

StringTokenizer st = new StringTokenizer("this is in china") ;//預設是空格為分割符
        while(st.hasMoreTokens()) {
            System.out.println(st.nextToken());
        }
        StringTokenizer st1 = new StringTokenizer("this is my ida,and this is also yours"," ,") ;   //自定義分割符
    while(st1.hasMoreTokens()) {
            System.out.println(st1.nextToken());
        }
StreamTokenizer st = new StreamTokenizer(new BufferedReader
                (new InputStreamReader(System.in))) ;
        st.nextToken() ;//獲得令牌
        String str = st.sval ;//取出令牌,sval為該類的靜態常量
        //表示一個文字,以製表符,換行符,空格為分割符
        st.nextToken() ;
        int a = (int) st.nval ;//nval為該類的靜態常量,表示讀取的是個數字
        System.out.println(str);
        System.out.println(a);

 

參考資料:

 

1. http://acm.hdu.edu.cn/

2. https://www.cnblogs.com/zhrb/p/6347738.html

3. https://www.acwing.com/blog/content/279/  (三種讀取方法的時間比較)

4. https://blog.csdn.net/shijiebei2009/article/details/17305223

5. https://www.jianshu.com/p/fa235c29fbea

6. https://blog.csdn.net/sunyanxiong123/article/details/75212717

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相關文章