본문 바로가기
CP, PS/토막지식

PS관련 토막 지식 - 인코딩

by 리나그(ReenAG) 2021. 7. 29.
728x90
반응형

인코딩은 어렵다. 어떤 비트가 어떤 것을 원하는지 알아야하기 때문이다. 솔직히, UTF-8인코딩은 정말 속 터지는 저장 방식이 아닐 수 없다. 내가 읽은 "조엘 소프트웨어"라는 책에서도 주로 그런 이야길 자주 한다. 하지만 결국 개발자라면 어쩔 수 없이 기본적인 내용은 알아야겠지?

 

인코딩을 직접 문제를 풀면서 알아보자 :

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

 

11283번: 한글 2

한글의 각 글자는 초성, 중성, 종성으로 이루어져 있고, 이 세 가지를 모아써서 한 글자를 나타낸다. 초성은 ㄱ, ㄲ, ㄴ, ㄷ, ㄸ, ㄹ, ㅁ, ㅂ, ㅃ, ㅅ, ㅆ, ㅇ, ㅈ, ㅉ, ㅊ, ㅋ, ㅌ, ㅍ, ㅎ로 총 19개가 있

www.acmicpc.net

UTF-8은 이렇게 정보를 저장한다 :

이게 그나마 제~일 직관적인 이해 방법이다.

여기서 X표시 된 부분에 저장이 된다.

한글의 경우, 3바이트로 저장된다. 1110(XXXX)->여기 + 10(XXXXXX)-> 여기 + 10(XXXXXX)-> 여기 총 16개의 X에 넘버링이 쪼개져서 저장된다. "가"는 16진수로 AC00, 2진수로 1010110000000000 ->16자리 인데, 이걸 쪼개서 저장한다고 생각하면 된다. 그래서 넘버링을 빠르고 간편하게 얻을 방법이 없다...

 

아무튼, 각각의 비트값을 알아내어 numbering에 더해 유니코드 값을 알아내는 코드는 이렇다 :

#include<iostream>
#include<bitset>

using namespace std;

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    string han = "가";
    cin >> han;
    int numbering = 1;

    for(int i = 0; i < 6; i++){
        if((char)(1 << i) & han[2]){
            numbering += (1 << i);
        }
    }
    for(int i = 6; i < 12; i++){
        if((char)(1 << (i - 6)) & han[1]){
            numbering += (1 << i);
        }
    }
    for(int i = 12; i < 16; i++){
        if((char)(1 << (i - 12)) & han[0]){
            numbering += (1 << i);
        }
    }
    cout << (numbering - 0xAC00);

    return 0;
}

 

인코딩이 헷갈린다면 참조 :

https://jeongdowon.medium.com/unicode%EC%99%80-utf-8-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-b6aa3f7edf96

 

Unicode와 UTF-8 간단히 이해하기

유니코드(Unicode)

jeongdowon.medium.com

UTF-8의 취지는 알겠는데, 파스칼 문자열과 C문자열의 단점만을 합친듯한 이런 애매모호한 인코딩 방식이 어째서 세계적으로 쓰이게 되었는지는 의문.

 

728x90
반응형