일기, 잡다한것

백준 JAVA 입출력 끄적

khj1999 2024. 8. 20. 21:58

입력

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        String str = br.readLine();
        int n = Integer.parseInt(br.readLine())
	}
}

java.io.BufferedReader를 임포트 해줘야하고 BufferedReader를 사용하려면 IOException도 임포트 하고
public static void main(String[] args) throws IOException 이런식으로 작성해줘야 한다.

 

그런데 이것은 한 줄씩 입력 받으므로 한 줄에 예를들어 "13 12 40 30" 뭐 이런식으로 입력을 받으면 코드를 더 추가해야한다

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        // 입력을 받기 위해 BufferedReader 생성
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        // 한 줄의 입력을 받음
        String input = br.readLine();
        
        // StringTokenizer를 이용해 공백을 기준으로 입력을 분리
        StringTokenizer st = new StringTokenizer(input);
        
        // 입력받은 숫자의 개수를 알아냄
        int count = st.countTokens();
        
        // 분리된 숫자를 저장할 배열 생성
        int[] numbers = new int[count];
        
        // StringTokenizer를 이용해 분리된 문자열을 순서대로 배열에 저장
        for (int i = 0; i < count; i++) {
            numbers[i] = Integer.parseInt(st.nextToken());
        }
        
        // 배열 출력 (확인용)
        for (int num : numbers) {
            System.out.print(num + " ");
        }
    }
}

공백 기준으로 입력을 분리해 값을 저장한 후 입력

 

출력

System.out.println() 을 사용하는게 편하고 좋겠으나 속도가 너무 느린 관계로

BufferedWriter를 사용해야한다 참고로 flush()를 안해주면 출력이 안된다

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(System.out));
        
        for (int i = 0; i < 1000000; i++) {
            bf.write(i + "\n");
        }
        
        bf.flush();  // 출력 버퍼를 강제로 비워서 남아 있는 데이터를 출력
    }
}

근데 이것도 마찬가지로 IOException 임포트를 해주고 사용해야한다.

 

 

또 다른 방법으로는 StringBuilder가 있다.

자바를 공부한지 얼마 되지 않아서 제대로 이해 한 것이 맞는지는 잘 모르겠지만 스트링 빌더 객체에 스트링을 계속 추가해서 모은다음

한번에 출력하는 것으로 이해했다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        // 입력을 받기 위해 BufferedReader 생성
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        // 한 줄의 입력을 받음
        String input = br.readLine();
        
        // StringTokenizer를 이용해 공백을 기준으로 입력을 분리
        StringTokenizer st = new StringTokenizer(input);
        
        // 입력받은 숫자의 개수를 알아냄
        int count = st.countTokens();
        
        // 분리된 숫자를 저장할 배열 생성
        int[] numbers = new int[count];
        
        // StringTokenizer를 이용해 분리된 문자열을 순서대로 배열에 저장
        for (int i = 0; i < count; i++) {
            numbers[i] = Integer.parseInt(st.nextToken());
        }
        
        // StringBuilder를 사용해 빠르게 출력할 문자열을 생성
        StringBuilder sb = new StringBuilder();
        
        for (int num : numbers) {
            sb.append(num).append(" ");
        }
        
        // 결과 출력
        System.out.println(sb.toString().trim());
    }
}

이것은 출력할때 System.out.println() 사용해도 괜찮은 속도가 나온다고 해서 한번 사용해봐야 할 것 같다.

원리는 StringBuilder는 내부적으로 가변적인 배열을 사용하여 문자열을 추가할 때마다 새로운 객체를 생성하지 않기 때문에

String 객체를 반복적으로 사용하는 것보다 성능이 뛰어난 것으로 알고 있다.

 

참고로 StringBuffer도 있는데 멀티 쓰레드 환경에서 동기화가 필요하면 StringBuffer를 사용하는 것이 맞지만

백준을 푸는데 멀티 쓰레드는 필요 없다고 생각이들고 속도도 또 StringBuilder가 동기화가 없어서 StringBuffer보다 조금이라도

더 빠르기 때문에 StringBuilder를 사용하는것이 좋은거 같다.

 

입,출력이 매우 귀찮지만 어쩔수가 없다 사실 이런게 싫어서 코딩테스트(알고리즘 문제 풀이)진행을 C++로 주로 했었는데

취업은 해야하는데 도망치기만해선 답도 없을 것 같아서 이렇게 공부를 하는중이다.

 

백준에서 측정한 입출력 속도 표

https://www.acmicpc.net/blog/view/56

https://www.acmicpc.net/blog/view/57