85.22 wchar_t 사용하기
wchar_t는 와이드 문자(wide character)를 저장하기 위한 자료형입니다. 보통 영문 알파벳은 1바이트로 표현하지만 유니코드는 2바이트 이상으로 표현하기 때문에 wchar_t에 저장해야 합니다.
Visual Studio에서는 wchar_t를 unsigned short로 정의하고 있고, GCC에서는 4바이트로 정의하고 있습니다. 단, GCC에서 -fshort-wchar 옵션을 사용하면 wchar_t를 2바이트로 사용할 수 있습니다.
wchar_t 문자와 문자열은 다음과 같이 따옴표 앞에 L을 붙여서 표현합니다.
wchar_t wc1 = L'a'; wchar_t *ws1 = L"Hello, world!"; // 와이드 문자열은 L을 붙임 wchar_t *ws2 = L"안녕하세요.";
다음과 같이 wchar_t 문자열은 w가 붙은 함수를 사용해야 합니다(wchar.h 헤더 파일에 선언되어 있습니다).
wchar1.c
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <wchar.h> int main() { wchar_t ws1[20]; wscanf(L"%s", ws1); wprintf(L"%s\n", ws1); // 두 번째 인수에는 wchar_t 문자열의 문자 개수를 구해서 넣어줌 swprintf(ws1, sizeof(ws1) / sizeof(wchar_t), L"%s", L"Hello, world!"); FILE *fp = _wfopen(L"hello.txt", L"w+"); // _wfopen 함수는 표준이 아니므로 리눅스에서는 사용할 수 없음 // 리눅스에서는 fopen 함수 사용 // FILE *fp = fopen("hello.txt", "w+"); // 리눅스에서는 %s 대신 %S 사용 wchar_t ws2[20]; wchar_t ws3[20]; fwprintf(fp, L"%s", L"C Language"); rewind(fp); fwscanf(fp, L"%s %s", ws2, ws3); wprintf(L"%s %s\n", ws2, ws3); rewind(fp); fputws(L"Wide Character", fp); rewind(fp); fgetws(ws2, 20, fp); wprintf(L"%s\n", ws2); rewind(fp); fputwc(L'X', fp); rewind(fp); wint_t wc1 = fgetwc(fp); putwchar(wc1); fclose(fp); return 0; }
실행 결과
Hello (입력) Hello C Language Wide Character X
swprintf 함수는 swprintf(ws1, sizeof(ws1) / sizeof(wchar_t), L"%s", L"Hello, world!");와 같이 버퍼와 함께 wchar_t 문자열의 문자 개수를 넣으면 됩니다. 여기서 wchar_t ws1[20];일 때 sizeof(ws1)만 지정하면 wchar_t 크기가 2바이트이므로 40이 나옵니다. 따라서 sizeof(ws1)을 sizeof(wchar_t)로 나누어서 문자 개수를 구하도록 만들어야 합니다.
_wfopen 함수는 표준이 아니며 Visual Studio에서만 사용할 수 있고 리눅스에서는 사용할 수 없습니다.
wchar_t 문자열 처리 함수는 str 대신 wcs로 시작합니다. 예를 들어 strcpy의 와이드 문자 버전은 wcscpy입니다.
wchar2.c
#define _CRT_SECURE_NO_WARNINGS #include <wchar.h> int main() { wchar_t ws1[20] = L"Hello, world!"; wchar_t ws2[20]; wprintf(L"%d\n", wcslen(ws1)); // 리눅스에서는 %s 대신 %S 사용 wcscat(ws1, L"123"); wprintf(L"%s\n", ws1); wcscpy(ws2, ws1); wprintf(L"%s\n", ws2); wprintf(L"%d\n", wcscmp(ws1, ws2)); wchar_t *ptr = wcschr(ws1, L'o'); wprintf(L"%s\n", ptr); ptr = wcsrchr(ws1, L'l'); wprintf(L"%s\n", ptr); ptr = wcsstr(ws1, L"wor"); wprintf(L"%s\n", ptr); wchar_t ws3[20] = L"The Little Prince"; wchar_t *next; ptr = wcstok(ws3, L" ", &next); // next에는 다음번에 자를 문자열의 포인터가 들어감 while (ptr != NULL) { wprintf(L"%s\n", ptr); ptr = wcstok(NULL, L" ", &next); } return 0; }
실행 결과
13 Hello, world!123 Hello, world!123 0 o, world!123 ld!123 world!123 The Little Prince
리눅스에서 wprintf로 wchar_t 문자열을 출력할 때는 %s 대신 %S를 사용하면 됩니다. 참고로 C 언어에서 다국어 및 유니코드 처리는 매우 까다로운 분야입니다. 여기서는 이런 자료형과 함수가 있다는 것 정도만 알아두면 됩니다.
실제로 전문적인 소프트웨어는 IBM이 오픈 소스로 공개한 ICU(International Components for Unicode) 라이브러리를 많이 사용합니다. 한글화가 잘 된 게임이라면 ICU를 사용하고 있을 가능성이 큽니다. 시드 마이어의 <문명 V>, 오픈 오피스, 이클립스, Node.js, 파이썬, OS X, iOS, 사파리, 안드로이드, 크롬, 구글 지도 등 많은 제품이 ICU를 사용합니다. 다국어 지원이 필요한 소프트웨어를 개발한다면 ICU 같은 전문적인 라이브러리를 검토해보세요.