Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++ mbrtowc() 함수 완벽 가이드: 멀티바이트 문자를 와이드 문자로 변환하기


C++ 프로그래밍에서 문자 인코딩을 다루다 보면 멀티바이트(multibyte) 문자와 와이드(wide) 문자 사이의 변환이 필요한 순간이 자주 찾아옵니다. 이 글에서는 C++ STL에서 제공하는 std::mbrtowc() 함수의 동작 원리, 문법, 매개변수, 반환 값 그리고 실전 예제까지 체계적으로 살펴보겠습니다.

std::mbrtowc()란 무엇인가?

std::mbrtowc()는 C++ 표준 라이브러리에 내장된 함수로, <cwchar> 헤더 파일에 정의되어 있습니다. 함수 이름은 "multi-byte re-startable to wide character"의 약자로, 이름 그대로 좁은(narrow) 멀티바이트 문자 하나를 와이드 문자 표현으로 변환하는 역할을 합니다.

여기서 말하는 멀티바이트 문자란 UTF-8처럼 한 문자가 1바이트부터 여러 바이트까지 가변적으로 표현되는 문자를 의미합니다. 영어 알파벳은 보통 1바이트로 표현되지만, 독일어의 ß나 한글·한자 같은 문자는 2바이트 이상으로 표현되기 때문에 단순한 바이트 단위 처리만으로는 올바르게 다룰 수 없습니다. mbrtowc()는 이러한 가변 길이 문자열을 안전하게 해석할 수 있도록 도와주는 함수입니다.

문법

size_t mbrtowc( wchar_t* pwc, char* str, size_t n, mbstate_t* ps);

매개변수

이 함수는 다음과 같은 매개변수를 받습니다.

  • pwc − 변환된 와이드 문자가 저장될 위치를 가리키는 포인터입니다.
  • str − 입력으로 사용되는 멀티바이트 문자열입니다.
  • n − 검사할 최대 바이트 수입니다.
  • ps − 멀티바이트 문자열을 해석하는 동안 변환 상태를 유지하는 상태 객체(state object)에 대한 포인터입니다.

반환 값

이 함수는 상황에 따라 다른 값을 반환합니다.

  • 0 − 변환 대상인 str의 문자가 널(NULL) 문자일 때 반환됩니다.
  • 1 ~ n − 문자열 *str에서 실제로 변환된 멀티바이트 문자의 바이트 수입니다.
  • -2 − 다음 n바이트가 아직 불완전하지만, 지금까지 읽은 부분은 유효한 멀티바이트 문자의 일부일 때 반환됩니다.
  • -1 − 인코딩 오류가 발생했을 때 반환되며, 이 경우 *pwc에는 아무것도 기록되지 않습니다.

예제 1: UTF-8 문자열 변환하기

다음 예제는 UTF-8로 인코딩된 문자열을 한 글자씩 변환하여 각 문자가 몇 바이트로 구성되어 있는지 출력합니다.

#include <bits/stdc++.h>
using namespace std;

void print_(const char* ch){
    mbstate_t temp = mbstate_t();
    int cal = strlen(ch);
    const char* i = ch + cal;
    int total;
    wchar_t con;
    while ((total = mbrtowc(&con, ch, i - ch, &temp)) > 0){
        wcout << L"다음 " << total << L"바이트는 문자 " << con << L'\n';
        ch += total;
    }
}

int main(){
    setlocale(LC_ALL, "en_US.utf8");
    const char* len = u8"z\u00df\u6c34";
    print_(len);
}

출력

다음 1바이트는 문자 z
다음 2바이트는 문자 ß
다음 3바이트는 문자 水

위 예제에서 문자 'z'는 UTF-8에서 1바이트, 'ß'(U+00DF)는 2바이트, '水'(U+6C34)는 3바이트로 각각 표현됩니다. mbrtowc()는 이를 정확히 구분하여 각 문자의 실제 바이트 크기를 반환하는 것을 확인할 수 있습니다.

예제 2: 불완전한 바이트 시퀀스 처리

다음 예제는 수학 기호가 포함된 문자열 끝에 불완전한 바이트(\xC2)를 추가한 경우입니다.

#include <bits/stdc++.h>
using namespace std;

void print_(const char* ch){
    mbstate_t temp = mbstate_t();
    int cal = strlen(ch);
    const char* i = ch + cal;
    int total;
    wchar_t con;
    while ((total = mbrtowc(&con, ch, i - ch, &temp)) > 0){
        wcout << L"다음 " << total << L"바이트는 문자 " << con << L'\n';
        ch += total;
    }
}

int main(){
    setlocale(LC_ALL, "en_US.utf8");
    const char* len = u8"\xE2\x88\x83y\xE2\x88\x80x\xC2";
    print_(len);
}

출력

다음 3바이트는 문자 ∃
다음 1바이트는 문자 y
다음 3바이트는 문자 ∀
다음 1바이트는 문자 x

존재 기호 '∃'(U+2203)와 전칭 기호 '∀'(U+2200)는 각각 3바이트로 인코딩됩니다. 문자열 끝의 \xC2는 2바이트 문자의 시작 바이트이지만 나머지 바이트가 없어 불완전한 시퀀스가 되며, 이때 mbrtowc()는 -2를 반환하고 반복문이 종료됩니다. 이처럼 잘린 데이터나 스트림 입력을 처리할 때에도 함수가 안전하게 동작함을 보여줍니다.

마무리

std::mbrtowc()는 멀티바이트 문자열을 와이드 문자로 안전하게 변환할 수 있는 강력한 도구입니다. 특히 UTF-8 같은 가변 길이 인코딩을 다룰 때 각 문자의 바이트 경계를 정확히 파악할 수 있어, 국제화(i18n) 처리나 파일·네트워크 스트림 파싱에 유용하게 활용됩니다. 반환 값을 꼼꼼히 확인하는 습관을 들이면 불완전하거나 잘못된 인코딩 데이터도 견고하게 처리할 수 있습니다.