본문 바로가기
C++, MFC

[C++/MFC] 멀티바이트, 유니코드 개념 정리 / 문자열 변환 방법

by dev_drive 2022. 9. 19.
반응형

 

멀티바이트란?

유니코드가 생기기 이전에 다국어를 표현하기 위해 사용했던 방식으로 최초에는 싱글바이트로 숫자, 영어만 표현되도록 1byte만을 사용해서 문자를 처리했는데 한국어, 일본어, 중국어 등 1byte만으로는 표현되지 않는 언어들을 표현하기 위해 만들어진 개념으로 MBCS(MultiByte Character Set) 또는 가변 너비 인코딩이라고도 불린다.

 

 

 

유니코드란?

멀티 바이트는 영어, 숫자 등 반각문자는 1byte, 한국어, 중국어 등 전각 문자는 2byte를 사용해서 표현하는데 이런 가변적인 특성을 없애고 모든 문자를 2byte로 표현하기 위해 정의한 방식이다.   하지만 유니코드라고 모두 2byte인것은 아니고 유니코드도 인코딩에 따라 가변적으로 적용되기도 한다. 

 

 

 

MFC(Visual C++)프로젝트의 문자 집합 설정화면 입니다.

멀티바이트와 유니코드 문자 집합을 선택하여 어떤 방식으로 문자를 처리할 지 설정할 수 있습니다. 

 

하지만 문자를 처리할 때 멀티바이트는 기본적으로 char를 사용하고 유니코드는 wchar_t를 사용하는데 

프로젝트 설정을 바꾸면 모든 변수를 바꿔줘야 하는 문제가 생깁니다. 

 

이런 문제를 해결하기 위해 나온 개념이 바로 T 매크로입니다.

TCHAR를 변수로 사용하면 멀티바이트에서는 char로, 유니코드에서는 wchar_t로 인식하는 것이죠.

 

 

 

 

자주 사용하는 T 매크로의 종류

  멀티바이트 유니코드 T 매크로
문자열 "" L"" _T("")
문자열 길이 strlen wcslen _tcslen
문자열 복사 strcpy wcscpy _tcscpy
문자열 합치기 strcat wcscat _tcscat
문자열 자르기 strtok wcstok _tcstok
문자열 비교 strcmp wcscmp _tcscmp
MFC 문자열 CStringA CStringW CString

예전엔 멀티바이트와 유니코드를 공존해서 사용했었는데 요즘은 특별한 경우가 아니라면 웬만하면 유니코드로 프로그램을 구현하긴 하지만 혹시 모르니 T 매크로를 사용하는 습관을 들이시는게 좋습니다.

 

 

 

문자열 길이 계산 시 유의사항

char* szMulti	= "멀티1234"; 
wchar_t* szUni	= L"유니1234";
int nLenMulti	= strlen(szMulti);  
int nSizeMulti	= sizeof(char) * nLenMulti;
int nLenUni	= wcslen(szUni);  
int nSizeUni	= sizeof(wchar_t) * nLenUni;

char는 멀티바이트 형태, wchar_t는 유니코드로 표현된 문자열입니다. 

strlen, wcslen은 각 문자열에 대한 길이를 구하는 함수입니다. 

결과가 어떻게 나올지 짐작이 되시나요?  답은 아래를 확인해주세요.

 

더보기
nLenMulti 	= 8
nSizeMulti 	= 8
nLenUni 	= 6
nSizeUni 	= 12

멀티바이트에서는 문자열 길이를 한글 2, 영어(숫자)1로 계산하고
유니코드에서는 단순히 문자 개수로 계산합니다. 
헷갈릴 수 있는 부분이니 개발할 때 잘 체크하셔야 합니다.

멀티바이트에서 문자 개수를 구하려면 _mbslen() 함수를 이용합니다.

 

 

멀티바이트 < - > 유니코드 문자열 변환 방법

■ 멀티바이트 -> 유니코드

    1. Win32Api (MultiByteToWideChar) 이용

char* inbuf = "멀티1234";
int isize = strlen(inbuf);
int nLength = MultiByteToWideChar(CP_ACP, 0, inbuf, isize, NULL, NULL);

int nLen = sizeof(WCHAR) * (nLength + 1);
WCHAR* outbuf = new WCHAR[nLen];
memset(outbuf, 0, nLen);

MultiByteToWideChar(CP_ACP, 0, inbuf, isize, outbuf, nLength);

delete[] outbuf;

 

    2. ATL Conversion 클래스 (CA2W) 이용

char* inbuf = "멀티1234";
CStringW sUni = CA2W(inbuf);

 

    3. COM 클래스 (_bstr_t) 이용

char* inbuf = "멀티1234";
CStringW sUni = _bstr_t(inbuf);

 

 

■ 유니코드 -> 멀티바이트

    1. Win32Api (WideCharToMultiByte) 이용

wchar_t* inbuf = L"유니1234";
int nLength = WideCharToMultiByte(CP_ACP, 0, inbuf, -1, NULL, 0, NULL, NULL);

char* outbuf = new char[nLength + 1];
memset(outbuf, 0, nLength + 1);

WideCharToMultiByte(CP_ACP, 0, inbuf, -1, outbuf, nLength, NULL, NULL);
	
delete[] outbuf;

 

    2. ATL Conversion 클래스 (CW2A) 이용

wchar_t* inbuf = L"유니1234";
CStringA sMulti = CW2A(inbuf);

 

    3. COM 클래스 (_bstr_t) 이용

wchar_t* inbuf = L"유니1234";
CStringA sMulti = _bstr_t(inbuf);

 

 

※ 참고로 ATL, COM클래스는 T 매크로를 지원해서 어떤 형식이 들어오든 원하는 형태로 변경할 수 있습니다. 

// ATL 클래스
TCHAR* inbuf 	= _T("문자1234");
CStringA sMulti = CT2A(inbuf);
CStringW sUni 	= CT2W(inbuf);

// COM 클래스
TCHAR* inbuf 	= _T("문자1234");
CStringA sMulti = (LPCSTR)_bstr_t((LPCTSTR)inbuf);
CStringW sUni 	= (LPWSTR)_bstr_t((LPCTSTR)inbuf);

 

반응형

댓글