[1. 개요]
UTF-8 인코딩 방식에 대해서 정리한다.
UTF-8 은 멀티바이트 형태의 문자 인코딩 방식이다.
- 경우에 따라 문자 하나를 1바이트 혹은 2바이트, 3바이트 최대 4바이트로 인코딩 한다.
- 첫번째 바이트의 bit 패턴을 통해서, 몇 바이트로 표현 된 문자인지 알 수 있다.
첫번째 byte 의 bit 패턴이 다음과 같을 때,
- b0xxx_xxxx => 1byte
- b110x_xxxx => 2byte
- b1110_xxxx => 3byte
- b1111_0xxx => 4byte
그리고 인코딩 된 바이트 수에 따라서 인코딩 패턴은 아래와 같다.
- 1byte : b0xxx_xxxx
- 2byte : b110x_xxxx, b10xxxxxx
- 3byte : b1110_xxxx, b10xxxxxx, b10xxxxxx
- 4byte : b1111_0xxx, b10xxxxxx, b10xxxxxx, b10xxxxxx
UTF-8 로 인코딩 된 문자열을 디코딩 하려면,
- 편의 상, 유니코드로 변경하는 것을 디코딩이라 생각하도록 한다.
- 1byte 로 인코딩 된 문자의 경우, 그 값을 그대로 사용
=> 단순히 이 값을 (wchar_t)에 저장 - 2byte 로 인코딩 된 문자의 경우, 하위 바이트의 하위 6bit 값과, 상위 바이트의 하위 5bit 를 결합하여 사용
=> 총 11bit 를 (wchar_t) 에 저장. - 3byte 로 인코딩 된 문자의 경우, MSB 를 제외 한 바이트들의 하위 6bit 값과, MSB 의 하위 4bit 를 결합하여 사용.
=> 총 16bit 를 (wchar_t) 에 저장. - 4byte 로 인코딩 된 문자의 경우, MSB 를 제외 한 바이트들의 하위 6bit 값과, MSB 의 하위 3bit 를 결합하여 사용.
=> 총 21bit 를 (wchar_t) 에 저장.
widechar 자료형을 의미하는 wchar_t 는 윈도우와 리눅스에서 그 바이트 크기가 다르다.
- 윈도우: UTF-16, 2byte
- 리눅스: UTF-32, 4byte
- 고정 된 크기로 문자를 인코딩 한다는게 중요하다.
다만, 현대 한글은 UTF-8 로 최대 3byte 로 표현하고,
유니코드로 변경 시, 이 중 16bit 만 사용하므로, 모두 2byte 로 표현할 수 있다.
- 유니코드로 현대 한글 자모는 [U+1100 ~ U+11FF] 범위 내 있고,
- 현대 한글 음절은 [U+AC00 ~ U+D7A3] 범위 내 있다.
[2. 예제]
#include <iostream>
#include <string>
unsigned int utf8_to_unicode(const std::string& utf8) {
unsigned int unicode = 0;
size_t num_bytes = utf8.size();
if (num_bytes == 1) {
unicode = utf8[0];
} else if (num_bytes == 2) {
unicode = ((utf8[0] & 0x1F) << 6) | (utf8[1] & 0x3F);
} else if (num_bytes == 3) {
unicode = ((utf8[0] & 0x0F) << 12) | ((utf8[1] & 0x3F) << 6) | (utf8[2] & 0x3F);
} else if (num_bytes == 4) {
unicode = ((utf8[0] & 0x07) << 18) | ((utf8[1] & 0x3F) << 12) | ((utf8[2] & 0x3F) << 6) | (utf8[3] & 0x3F);
} else {
throw std::invalid_argument("Invalid UTF-8 sequence");
}
return unicode;
}
void convert_utf8_to_unicode(const std::string& input) {
size_t i = 0;
while (i < input.size()) {
unsigned char first_byte = input[i];
// 첫 바이트의 비트 패턴에 따라 바이트 시퀀스 길이를 결정
size_t num_bytes = 0;
if ((first_byte & 0x80) == 0x00) {
num_bytes = 1; // 1바이트 문자 (ASCII)
} else if ((first_byte & 0xE0) == 0xC0) {
num_bytes = 2; // 2바이트 문자
} else if ((first_byte & 0xF0) == 0xE0) {
num_bytes = 3; // 3바이트 문자
} else if ((first_byte & 0xF8) == 0xF0) {
num_bytes = 4; // 4바이트 문자
} else {
throw std::invalid_argument("Invalid UTF-8 sequence");
}
// 현재 바이트와 그 다음 바이트들로 유니코드 코드 포인트 계산
std::string utf8_char = input.substr(i, num_bytes);
unsigned int unicode = utf8_to_unicode(utf8_char);
// 유니코드 출력
std::cout << "UTF-8 -> Unicode: U+" << std::hex << unicode << std::endl;
i += num_bytes;
}
}
int main()
{
std::string str = "안녕하세요";
convert_utf8_to_unicode(str);
return 0;
}
출력 |
UTF-8 -> Unicode: U+c548 UTF-8 -> Unicode: U+b155 UTF-8 -> Unicode: U+d558 UTF-8 -> Unicode: U+c138 UTF-8 -> Unicode: U+c694 |
[3. 예제, 디코딩]
#include <iostream>
#include <string>
std::string wstring_to_utf8(const std::wstring& wstr)
{
std::string result; // 변환된 UTF-8 문자열을 저장할 변수
// 주어진 wide string(wstr)에서 각 wchar_t 문자를 하나씩 처리
for (wchar_t wc : wstr) {
// 1바이트로 표현 가능한 ASCII 문자 (0x00 ~ 0x7F)
if (wc < 0x80) {
result.push_back(static_cast<char>(wc)); // ASCII 문자이므로 그대로 추가
}
// 2바이트로 표현 가능한 문자 (0x80 ~ 0x7FF)
else if (wc < 0x800) {
result.push_back(0xC0 | (wc >> 6)); // 상위 6비트를 0xC0와 OR하여 첫 바이트
result.push_back(0x80 | (wc & 0x3F)); // 하위 6비트를 0x80과 OR하여 두 번째 바이트
}
// 3바이트로 표현 가능한 문자 (0x800 ~ 0xFFFF)
else {
result.push_back(0xE0 | (wc >> 12)); // 상위 4비트를 0xE0과 OR하여 첫 바이트
result.push_back(0x80 | ((wc >> 6) & 0x3F)); // 중간 6비트를 0x80과 OR하여 두 번째 바이트
result.push_back(0x80 | (wc & 0x3F)); // 하위 6비트를 0x80과 OR하여 세 번째 바이트
}
}
return result; // 변환된 UTF-8 문자열 반환
}
int main()
{
std::wstring wstr = L"안녕하세요";
std::string str = wstring_to_utf8(wstr);
std::cout << str << std::endl;
std::cout << "wstr length " << wstr.length() << std::endl;
std::cout << "str length " << str.length() << std::endl;
return 0;
}
출력 |
안녕하세요 wstr length 5 str length 15 |
'분류대기' 카테고리의 다른 글
[리눅스] goto 사용 시 컴파일 (0) | 2025.01.14 |
---|---|
[C++] struct byte align (0) | 2024.12.26 |
swagger-editor 설치 (0) | 2024.06.12 |
CUDA 설치하기, [윈도우, 리눅스] (0) | 2024.05.14 |
[내용 채워야 됨] CUDA 사용해보기 (0) | 2024.02.22 |