상냥한 세상 :: [백준]1000번: A+B (용어 정리포함)

본문으로 바로가기

https://www.acmicpc.net/problem/1000

 

1000번: A+B

두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.

www.acmicpc.net

  • 문제

재밌는 사칙연산이다. 머리속으로 컴파일(실행)하면 1+2=3인걸 금방 확인 할 수 있지만 막상 컴퓨터보고 1+2를 해오라고 코드를 짜는건 코딩을 처음접해보는 초심자에겐 어떻게 해야할지 시간이 조금걸린다. (나 역시도 그랬으니까..)

여기서부턴, 다양한 접근방법을 통해 어떻게 하면 조금더 빠른 결과를 도출해낼수 있는지 알아보도록 할것이다. 

 

우선 시작전에 몇가지 용어와 클래스(도구)들을 알아보고자 한다

 

소스파일: 프로그래밍 언어를 사용해서 만들고자하는 프로그램을 구현한파일 (내가지금 보고있는 그 화면이 소스파일일 것이다)

객체: 실제로 존재하는것. 사전적인 정의로는 실제로 존재하는 물체 뿐만이 아니라 개념이나 논리, 이론도 객체가 될 수 있음
클래스: 객체를 정의하는 틀 또는 설계도
※TV가 객체고 TV를 만들기위해 필요한 설계도가 클래스라고 보면된다.

변수:어떤 데이터(data)를 저장하기 위해 프로그램에 의해 '이름'을 할당받은 메모리공간, 언제든지 값이 변경될수도 있다. 

메서드: 작업에 필요한 도구
import: 현재 작성하고 있는 소스파일에 다른 클래스(도구)를 불러오는 역할 
Scanner: 입력장치(키보드)로 입력을 받아 그 값을 변수에 저장하는 역할

  • 코드1
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner in= new Scanner(System.in);
        int A=in.nextInt();
        int B=in.nextInt();
        
        System.out.println(A+B);
        
        in.close();
    }
}

System.in: 키보드와 같은 사용자로부터 입력을 받는 표준입력스트림 (그냥 입력할때 필요한 도구/메소드)

  • 사용법
  • Scanner in=new Scanner(System.in);
    int i=in.nextInt();
    in.close();


Scanner in =new Scanner(System.in);와 in.close();는 그냥 Scanner을 부를경우 같이 따라오는거라고 생각하자.


우리는 A+B를 출력하기위해 각각 A와 B라는 알파벳을 '변수'로 지정하고, 각 알파벳에 숫자를 넣고 덧셈하여 그 결과값을

System.out.println(A+B);로 출력할 것이다.

 

각 변수를 선언하는 방법은 간단하다. 

우선 우리는 정수형만 다룰것이므로 변수는 int형이여야한다. 

이후 int A까지 그대로 따라와보자. 

 

그런데 위에 코드를 보면 in.nextInt();란게 있다. 이건 표준 입출력 메소드라고 한다. 변수를 선언만하고 끝나는게 아니라 실제로 키보드로 숫자를 1을 눌러서 직접 넣어줘야 하는데 그걸위해 있는 일종의 '도구'라고 보면된다.

 

이제 int A=in.nextInt(); 로 적으면 된다.

B도 위와같은 방법으로 int B=in.nextInt();로 적으면 된다.

 

종합해서 출력문 System.out.println(A+B); 이 출구와도 같은 역할이고 int A=in.nextInt(); 와 int B=in.nextInt(); 은 중간작업장과 같은 개념이니.. 순서는 당연히

int A=in.nextInt();
int B=in.nextInt();

System.out.println(A+B); 
이 되겠다. 

 

물론 Scanner in =new Scanner(System.in);을 통해 작업을 시작해줬으면 작업종료와도 같은 역할이 있어야하니 말단에 in.close();를 적어주자. 


  • 결과


  • 코드2
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String[] str=br.readLine().split(" ");
        int a=Integer.parseInt(str[0]);//br.readLine()으로 불러오는대신 배열사용
        int b=Integer.parseInt(str[1]);
        System.out.println(a+b);
    }
}

이번에는 Scanner과는달리 BufferedReader, InputStreamReader, IOException 처음보는 3가지들이 나왔다. 
먼저 이것들이 뭔지 위에처럼 정리하고 진행하겠다.

Stream:자바에선 파일이나 콘솔의 입출력을 직접 다루지 않고, Stream이라는 흐름을 통해 다룸

(즉 자바에선 데이터는 Stream을 통해 입/출력 됨)

 

스트림에서 데이터는 한방향으로만 통신할 수 있다. 입력과 출력을 동시에 처리할 순 없다. 그래서 존재하는게 입력스트림/출력스트림이다.

InputStream: 스트림사용시 입력 스트림(통로)

InputStreamReader: Byte단위로 읽어들이는 InputStream을 통해 입력을 받고, 문자 단위로 데이터를 변환시키는 중개자 역할을 하는 클래스 

OutputStream: 스트림사용시 출력 스트림(통로)

 


Buffer: 데이터를 한곳에서 다른곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 임시 메모리 영역
※Scanner 보다 처리속도가 더 빠르고 효율적이다

BufferedReader: 버퍼 사용시 입력용

※BufferedReader을 사용시 문자열을 받는 대표적인 방법이 read()와 readLine() 메소드이다.

※read(): 문자1개만 읽어온다/ readLine(): 한 행을 읽어온다

BufferedWriter: 버퍼 사용시 출력용
Buffer flush:
버퍼에 남아있는 데이터들을 출력시킴(버퍼를 비우는 동작, 말그대로 찌꺼기 정리 라고 보면됨)

  • 사용법
  • BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
    int T = Integer.parseInt( br.readLine() );

※readLine()을 통해 읽어드린 문자 행을 Integer.parseInt()을 통해 정수형으로 반환후 정수형 변수 T에 저장(초기화)


자료형:저장되는 데이터의 종류에 따른 형태로, 저장되는 값의 종류와 범위에 따라 다르게 표현됨 

문자열: 메모리에 저장된 일련의 연속된 문자(character)들의 집합, 문장을 뜻하기도 함. 

"Happy Java"  
"a"  
"123"

String: '문자열'을 나타내는 자료형


배열(Array): 같은 타입의 여러 변수를 하나의 묶음으로 나타낸 것

String 배열: 문자를 배열에 담아서 int(정수형)가 아닌 문자열 형태(String)로 담는것

Element: 배열을 구성하는 각각의 값

※Power의 경우 P, O, W, E, R이 각각의 Element / 최진혁,최유빈,한이람,이고잉이 각각의 Element

Index: 배열의 위치를 가르키는 번호

※배열의 Index 번호는 항상 0부터 시작한다. 
length: 배열의 길이 

※Power의 경우 길이는 5다. 


  • 사용법
//배열의 생성과 선언
String[] 지정해줄 배열 이름 = new String[설정할 배열길이]


//배열의 초기화: 배열안에 내가 넣고싶은 element를 넣는 과정
//편의상 배열이름을 str, 배열의 총길이를 3이라고 하자.
//여기서 배열의 총 lengh: 3, Index는 0,1,2 , element는 Kim, Park, Lee다

//방법1
str[0]="Kim";
str[1]="Park";
str[2]="Lee";

//방법2
// 괄호{ }를 사용해 간단히 초기화할 수 있다.
String[] name = new String[]{"Kim", "Park", "Lee"};

//방법3
// new String[]을 생략할 수 있다.
String[] name = {"Kim", "Park", "Lee"};

이제 다시 코드를 보면, 

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

public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String[] str=br.readLine().split(" ");
        int a=Integer.parseInt(str[0]);//br.readLine()으로 불러오는대신 배열사용
        int b=Integer.parseInt(str[1]);
        System.out.println(a+b);
    }
}

 

※split(" ")은 영어 뜻 그대로 " " 사이에 있는 저 공백만큼 각 문자 사이에 공백을 끼워주는 역할

 

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

이를 통해 소스파일에 필요한 각각의 클래스들을 import해준다. 

 

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String[] str=br.readLine().split(" ");
        int a=Integer.parseInt(str[0]);//br.readLine()으로 불러오는대신 배열사용
        int b=Integer.parseInt(str[1]);

이후 위에서 언급한 Buffer의 사용법과 String 배열의 사용법을 통해 다음과 같이 써내려가준다. 

여기서 br.readLine()이 읽을것은 A+B에 넣을 숫자 그자체가아니라 배열에 저장한 str[0]과 str[1]의 각각의 element들이다. 

 

 System.out.println(a+b);

각각의 변수 a,b에 배열의 element들을 넣고 초기화 해주었으면 이제 다시 출력으로 불러와 제대로 출력해주도록 하자. 


  • 결과


  • Scanner보단 Buffer?

Scanner를 통해 입력을 받을경우 Space Enter를 모두 경계로 인식하기에 입력받은 데이터를 가공하기 매우 편리하다. 
하지만 그에비해 BufferedReader는 Enter만 경계로 인식하고 받은 데이터가 String으로 고정되기때문에 입력받은 데이터를 가공하는 작업이 필요할경우가 많다. Scanner에 비해 다소 사용하기 불편하다. 


하지만 많은 양의 데이터를 입력받을경우 BufferedReader를 통해 입력받는 것이 효율면에서 훨씬 낫다.

입력시 Buffer를 활용함으로써 작업속도 차이가 많이 난다.

 

Scanner의 결과

Buffered의 결과


  • 코드3
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 br=new BufferedReader(new InputStreamReader(System.in));
        
        String str=br.readLine();
        StringTokenizer st=new StringTokenizer(str," ");
        int a=Integer.parseInt(st.nextToken());
        int b=Integer.parseInt(st.nextToken());
        
        System.out.println(a+b);
    }
}

이번엔 StringTokenizer을 이용한 출력방법이다

StringTokenizer의 역할: 앞서서 사용했던 split(" ")과 같다. 문자사이의 공백을 만들어 주기 위해서이다. 

  • 사용법
  • String abc = "써넣을 내용"
    StringTokenizer st = new StringTokenizer(abc, 구분자);
    
    
    //예시1
    //구분자가 없는상태
    String s = "2020년 2월 15일";
    StringTokenizer tokenizer = new StringTokenizer(s); //공백을 기준으로 문자열 s를 나누기 위한 객체
    
    //예시2
    //구분자가 있는상태
    String s = "2020-02-15";
    StringTokenizer tokenizer = new StringTokenizer(s, "-");
    
    
    //StringTokenizer들의 여러가지 메소드들
    int countTokens(): 남아있는 토큰의 개수를 반환한다.
    boolean hasMoreTokens():남아있는 토큰이 있으면 true, 더 이상 토큰이 없으면 false
    String nextToken():토큰을 꺼내온다.

 


사용법을 알았으니 본격적으로 시작해보자. StringTokenizer또한 java.util 패키지에 있으므로 import 해준다음 객체생성을 하자

import java.util.StringTokenizer;

 

이후 StringTokenizer의 사용법을 참고하여 둘중에 한가지 방법으로 사용하면된다. 차이는 없다. 어느게 간결해보이냐 그차이일뿐

String str = br.readLine();
StringTokenizer st = new StringTokenizer(str," ");

//또는

StringTokenizer st = new StringTokenizer(br.readLine()," ");

 

 

nextToken()을 사용해 구분자로 구분된 문자열이 담긴 변수를 차례대로 꺼내도록 하자. 그럼 문자열이 반환된다. 

이때 문자열은 반환됨과 동시에 (꺼내어짐과 동시에) 해당객체에서 사라지게 된다.

st.nextToken();

 

꺼낸 문자열을 정수형으로 변환하는  Integer.parseInt()을 사용후 정수형 변수 a에 넣고 저장(초기화)

int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());

 

마지막으로 저장한 두 변수를 출력하기위한 코드도 작성해주자

System.out.println(a+b);

  • 결과


  • 코드1,2,3의 속도비교

Scanner 사용
Buffered와 Split 사용
Buffered와 StringTokenizer 사용

 

결론적으로 StringTokenizer가 Scanner보다 처리속도면에서 훨씬 효율적인것을 보여주고 있다. 

'Computer Science > BAEKJOON JAVA Practice' 카테고리의 다른 글

[백준]10098번: AxB  (0) 2021.12.22
[백준]1001번: A-B  (0) 2021.12.22
[백준]10171번: 고양이  (0) 2021.12.22
[백준]10718번: We love kriii  (0) 2021.12.22
[백준]2557번: Hello World  (0) 2021.12.22