BOJ

[백준 11720번/JAVA] 숫자의 합 | charAt(), getBytes()

syj0522 2024. 3. 6. 23:52

문제

백준 11720번

첫 줄에 100 이하의 자연수 N을 입력받고,
둘째 줄에 N개의 숫자를 공백 없이 입력받는다.
입력받은 숫자들의 합을 구한다.

풀이

  • 입력받는 수의 자릿수가 0~100이므로 int, long으로 받을 수 없다.
  • 데이터 표현 범위
    • int : -2,147,483,648 ~ 2,147,483,647 -> 최대 10자리
    • long : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 -> 최대 19자리
  • 따라서 String으로 입력받고 각 자릿수를 int형으로 변환한 후 덧셈해야 한다.
  • 3가지 방법을 사용
    (1) Scanner + charAt() + getNumericValue()
    (2) BufferedReader + charAt() 
    (3) BufferedReader + getBytes()

코드

(1) Scanner + charAt() + getNumericValue()

import java.util.*;

public class Main {
    public static void main(String[] args){
        //갯수 입력받기
        //갯수만큼 숫자 입력받기(공백없이) >> String으로 받기
        //charAt()으로 하나씩 떼서 int로 변경
        //덧셈 후 출력
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();
        String str = sc.next();

        int sum = 0;
        for(int i=0; i<N; i++) {
            sum += Character.getNumericValue(str.charAt(i));
        }
        System.out.println(sum);
    }
}

java.lang.Character.getNumericValue(char)는 숫자 형태의 char을 int로 변환하는 메서드이다.

(2) BufferedReader + charAt() 

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int N = Integer.parseInt(br.readLine());
        String str = br.readLine();

        int sum = 0;

        for(int i=0; i<N; i++) {
            sum += str.charAt(i)-'0';
            //sum += str.charAt(i)-48;
        }
        System.out.println(sum);
    }
}
str.charAt(i)

먼저, 문자열을 이루는 문자 하나하나를 char로 변경한다.

sum += str.charAt(i)-'0'
//또는
sum += str.charAt(i)-48

char값에 '0'값(문자 '0'의 유니코드값) 또는 숫자 48을 빼준다.

 

  • 자바는 피연산자를 4byte 단위로 저장하므로, 2byte인 char타입이라도 둘이 연산을 하게 되면 자동으로 4byte인 int타입으로 변환되어 계산된다. 예를 들어 '5'와 '4'라는 char형 문자 간에 뺄셈을 하면 두 문자가 int타입의 유니코드 값으로 변환된 후 연산이 이루어진다. 문자 '5'의 유니코드 값은 53, 문자 '4'의 유니코드 값은 52이므로 result에는 정수값 1이 저장된다.
char c1 = '5';
char c2 = '4';
int result = c1 - c2; //'5'의 유니코드 값 - '4'의 유니코드 값 저장

 

  • 유니코드 (Unicode)
문자 '0' '1' '2' '3' '4' '5'
10진 48 49 50 51 52 53

 

  • 자바에서는 문자 상수가 사용될 때 이를 해당 문자의 유니 코드 값으로 간주한다. 따라서 '0'이라는 문자 상수는 해당 문자의 유니 코드 값인 48로 간주된다. '0'과 48은 같은 의미이다.

따라서 char형 문자에 -48 또는 -'0'을 해주면 문자와 동일한 정수값을 구할 수 있다.

 

(3) BufferedReader + getBytes()

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		int sum = 0;
        br.readLine();
		
        //for-each문으로 문자를 하나씩 읽는다.
        for (byte res : br.readLine().getBytes()){ //readLine()으로 읽어들인 문자열을 byte[]로 변환하여 반환한다.
            sum += res-'0'; //UTF-16(유니코드 인코딩 방식)에 맞게 각 문자의 값을 저장하므로 '0'또는 48을 뺀다.
        }
		bw.write(sum+" ");
		bw.close();
	}
}
  • java.lang.String.getBytes() 메서드
    • String 포함 메서드이기 때문에 import할 필요가 없다.
    • 유니코드 문자열(String)을 지정된 charset을 사용해 바이트코드로 인코딩하고, 새로운 byte 배열에 결과를 저장해 반환하는 메서드이다.
    • 만약 getBytes()의 인자로 charset을 넘기지 않으면 사용자 플랫폼의 기본 charset으로 인코딩된다. 자바는 UTF-16을 사용한다.

아래에서부터 차례로

(1) Scanner + charAt() + getNumericValue()
(2) BufferedReader + charAt() 
(3) BufferedReader + getBytes()

Note

  • 명시적 타입 캐스팅을 했을 때 char값은 아스키코드값으로 변경된다. 
char c = '1'; int result_1 = (int)c; //char형 '1'을 int로 명시적 타입캐스팅 //1의 아스키코드값 출력 
//49 
int result_2 = Character.getNumericValue(c); //char값이 int로 변경됨 
//1
  • String.prototype.split()도 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나누는 메서드이다.
    하지만 구분자로 빈 문자열("")을 제공하면, 유니코드 문자 하나씩으로 나누는 것이 아니라 UTF-16 으로 나누게 되며 써로게이트 페어가 망가질 수 있다. 
  • 인코딩 : 사람이 이해하는 언어(문자, 숫자, 기호) -> 컴퓨터가 이해하는 언어(0, 1)
  • 디코딩 : 인코딩의 반대
  • charset : 인코딩을 위한 규칙 (ex. ASCII CODE, UNICODE..)
  • charset마다 인코딩 방식이 하나씩 있는데, UNICODE는 UTF-8(HTML), UTF-16(JAVA) 두 가지가 있다.