Windows에서의 유니코드(UNICODE)
1. 문자셋의 종류와 특성
- 아스키코드(ASCII): 미국에서 정의하고 있는 표준, 1바이트로 표현(256개까지 표현 가능)
- 유니코드(UNICODE): 문자를 균일하게 2바이트로 표현(65,536개 표현 가능)
- 문자셋: 문자들의 집합, 약속된 문자의 표현 방법
1) SBCS(Single Byte Character Set)
- 1바이트로 문자 표현
- 아스키 코드가 대표적으로 포함
2) MBCS(Multi Byte Character Set)
- DBCS(Double Byte Character Set)이라고도 함
- 문자를 표현 하는데 있어서 동일한 바이트 수를 적용하는 것이 아니라 다양한 바이트 수를 적용해서 문자를 표현
- 유니코드는 MBCS에 속하지 않음
- 영어는 1바이트, 한글은 2바이트로 처리됨
- 프로그램을 구현하는 데 있어서 주의 요함
3) WBCS(Wide Byte Character Set)
- 모든 문자를 2바이트로 처리
- 유니코드가 대표적으로 포함
2. MBCS 기반의 문자열
1) MBCS 예제
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "ABC한글";
int size = sizeof(str);
int len = strlen(str);
printf("배열의크기: %d \n", size);
printf("문자열의크기: %d \n", len);
return 0;
}
배열의 크기: 8
문자열의 크기: 7
- 영문은 1바이트, 한글은 2바이트로 처리되고 있음
- strlen은 문자열의 길이를 계산함에 있어서 NULL문자를 포함하지 않음
2) MBCS 예제 2
#include <stdio.h>
int main(void)
{
char str[] = "한글입니다";
int i;
for(i=0; i<5; i++)
fputc(str[i], stdout);
fputs("\n", stdout);
for(i=0; i<10; i++)
fputc(str[i], stdout);
fputs("\n", stdout);
return 0;
}
한글
한글입니다
3) MBCS의 문제점, 해결책 제시
- 영어는 1바이트, 한글은 2바이트로 처리
- 문자의 출력, 처리 프로그래밍에 있어서 주의를 기울여야 함
- MBCS의 문제점을 해결할 수 있는 것이 WBCS방식
- WBCS 방식은 모든 문자들을 2바이트로 처리, 모든 문자들을 동일한 바이트의 크기로 처리함
3. WBCS 기반의 프로그래밍
1) char를 대신하는 wchar_t
- char형 변수: 1바이트 메모리 공간만 할당
- wchar_t형 변수: 2바이트 메모리 공간이 할당, 유니코드 기반으로 문자를 표현하는 것이 가능
typedef unsigned short wchar_t;
2) "ABC"를 대신하는 L"ABC"
wchar_t str[] = L"ABC";
- 문자 L: 이어서 등장하는 문자열을 유니코드 기반(WBCS 기반)으로 표현, 각문자는 2바이트로 표현
- 유니코드에서는 문자열 끝을 의미하는 널문자도 2바이트로 처리
3) strlen을 대신하는 wcslen
#include <stdio.h>
#include <string.h>
int main(void)
{
wchar_t str[] = L"ABC";
int size = sizeof(str);
int len = strlen(str);
printf("배열의크기: %d \n", size);
printf("문자열길이: %d \n", len);
return 0;
}
1>c:\users\xxx\desktop\mbcs\mbcs\mbcs.cpp(27) : error C2664: 'strlen' : cannot convert parameter 1 from 'wchar_t [4]' to 'const char *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>MBCS - 1 error(s), 0 warning(s)
- strlen 함수는 SBCS 기반(아스키코드 기반)문자열을 처리하기 위한 함수
strlen (const char * str)
- sizeof는 연산자: 배열에 어떠한 문자열이 저장되어 있건 상관없이 배열의 크기를 계산해서 반환
4) 문자열 조작 함수
SBCS, MBCS 기반 문자열 조작 함수 | WBCS 기반의 문자열 조작 함수 |
strlen | size_t wcslen(const wchar_t* string) |
strcpy | wchar_t* wcscpy(wchar_t* dest, const wchar_t* src) |
strncpy | wchar_t* wcsncpy(wchar_t* dest, const wchar_t* src, size_t cnt) |
strcat | wchar_t* wcscat(wchar_t* dest, const wchar_t* src) |
strncat | wchar_t* wcsncat(wchar_t* dest, const wchar_t* src, size_t cnt) |
strcmp | int wcscmp(const wchar_t* s1, const wchar_t* s2) |
strncmp | int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t cnt) |
- WBCS 기반 함수의 전달인자는 유니코드 기반 문자열
- size_t
typedef unsigned int size_t;
5) WBCS 예제
#include <stdio.h>
#include <string.h>
int main(void)
{
wchar_t str[] = L"ABC";
int size = sizeof(str);
int len = wcslen(str);
printf("배열의크기: %d \n", size);
printf("문자열의길이: %d \n", len);
return 0;
}
배열의 크기: 8
문자열의 길이: 3
6) 완전한 유니코드 기반으로 변환 1
- windows 2k 이상의 운영체제는 기본적으로 유니코드 지원
- windows 2k 이상의 운영체제에서 SBCS 방식 문자열 조작 함수 호출이 이루어 진다면 운영체제는 전달되는 문자열을 내부적으로 2바이트 유니코드 형식으로 변환, 성능에 영향을 미침
SBCS 함수 | WBCS 기반의 문자열 입,출력 함수 |
printf | int wprintf(const wchar_t* format[,argument]...) |
scan | int wscanf(const wchar_t* format [,argument]...) |
fgets | wchar_t* fgetws(wchar_t* string, int n, FILE* stream) |
fputs | int fputws(const wchar_t* string, FILE* stream) |
#include <stdio.h>
#include <string.h>
int main(void)
{
wchar_t str[] = L"ABC";
int size = sizeof(str);
int len = wcslen(str);
wprintf(L"Array Size: %d \n", size);
wprintf(L"String Length: %d \n", len);
return 0;
}
Array Size: 8
String Length: 3
* wprintf, fputws 같은 함수들을 통해 유니코드 기반으로 한글을 출력
- wprintf, fputws 함수전에 아래 함수가 호출되어야 함
- _wsetlocale 함수: 프로그램이 실행되는 나라 및 지역에 대한 정보를 설정하는 함수
_wsetlocale(LC_ALL, L"korean"); //#include "locale.h"
7) 완전한 유니코드 기반으로 변환 2
- 실행인자를 출력하는 코드
#include <stdio.h>
int main(int argc, char* argv[])
{
int i;
for(i=0; i<argc; i++)
fputws(argv[i], stdout);
return 0;
}
1>c:\users\xxx\documents\visual studio 2008\projects\wbcs3\wbcs3\wbcs3.cpp(8) : error C2664: 'fputws' : cannot convert parameter 1 from 'char *' to 'const wchar_t *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>WBCS3 - 1 error(s), 0 warning(s)
- char* argv[]를 wchar_t* argv[]로 변경하면 컴파일 에러는 발생하지 않지만 결과 출력이 안됨
- main 함수는 프로그램 실행시 전달되는 문자열을 MBCS 기반으로 구성하기 때문
8) 프로그램 실행시 전달되는 문자열을 유니코드 기반으로 구성하기 위한 main 함수
- wmain 함수에 대한 이해
- wmain 함수: 프로그램 실행시 전달되는 문자열을 유니코드 기반으로 구성
- 프로그램 실행시 추가로 문자열 AAA BBB CCC를 전달했을때 실행 결과 코드
#include <stdio.h>
int wmain(int argc, wchar_t* argv[])
{
for(int i=1; i<argc; i++)
{
fputws(argv[i], stdout);
fputws(L"\n", stdout);
}
return 0;
}
AAA
BBB
CCC
<참고 - visual studio 2008에서 실행 인자 지정 방법>
MBCS와 WBCS의 동시 지원
- 현존하는 시스템 모두가 완벽히 유니코드 기반을 지원하는 것이 아니므로 프로그램을 MBCS나 WBCS 기반으로 구현할 지 결정하는데에 어려움이 있음
- 프로그램은 한번만 구현하고 별다른 변경없이 MBCS와 WBCS 기반으로 실행되는 형태로 컴파일이 가능하기 위한 방법이 필요
1. #include <windows.h>
- windows.h: windows 기반 프로그래밍을 하는데 있어서 기본적으로 항상 포함 해야 하는 헤더 파일
2. windows에서 정의하고 있는 자료형
1) CHAR, WCHAR
- windows.h를 통해서 정의
typedef char CHAR;
typedef wchar_t WCHAR;
2) 문자열의 주소값을 저장할 수 있는 Windows 스타일의 자료형 정의
- windows 스타일의 자료형이 대문자로 구성
#define CONST const
typedef CHAR * LPSTR;
typedef CONST CHAR * LPCSTR;
typedef WCHAR * LPWSTR;
typedef CONST WCHAR * LPCWSTR;
#include <stdio.h>
#include <windows.h>
int wmain(int argc, wchar_t* argv[])
{
LPSTR str1 = "SBCS Style String 1";
LPWSTR str2 = L"WBCS Style String 1";
CHAR arr1[] = "SBCS Style String 2";
WCHAR arr2[] = L"WBCS Style String 2";
LPCSTR cStr1 = arr1;
LPCWSTR cStr2 = arr2;
printf("%s \n", str1);
printf("%s \n", arr1);
wprintf(L"%s \n", str2);
wprintf(L"%s \n", arr2);
return 0;
}
SBCS Style String 1
SBCS Style String 2
WBCS Style String 1
WBCS Style String 2
*typedef를 이용한 Windows 스타일 자료형 정의
- 선언의 편리성
- 확장의 용이성
3. MBCS와 WBCS를 동시 지원하기 위한 매크로
1) MBCS와 WBCS를 동시에 수용하는 형태의 프로그램 구현을 위한 매크로
- windows에 선언되어 있는 것을 간략화 한 것
#ifdef UNICODE
typedef WCHAR TCHAR;
typedef LPWSTR LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef CHAR TCHAR;
typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
- tchar.h에 선언되어 있는 내용을 편집해 놓은것
- windows.h에 tchar.h가 포함되어 있지 않으므로 추가로 포함 시켜야 됨
#ifdef _UNICODE
#define __T(x) L ## x
#else
#define __T(x) x
#endif
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
a. 유니코드와 MBCS를 동시 지원하는 프로그램의 예
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int wmain(void)
{
TCHAR str[] = _T("1234567");
int size = sizeof(str);
printf("string length: %d \n", size);
return 0;
}
string length: 16
b. 유니코드 define문을 주석처리 하고 실행
- 예상 출력값 8, 실제 출력값과 차이가 있음
- Winodws xp이상의 시스템에서 .NET 컴파일러 버전 2005 이상을 사용하는 경우 발생할 수 있음
//#define UNICODE
//#define _UNICODE
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int wmain(void)
{
TCHAR str[] = _T("1234567");
int size = sizeof(str);
printf("string length: %d \n", size);
return 0;
}
string length: 16
- 이유: visual studio에 미리 정의 되어 있기 때문..
- 주석처리를 하지 않았을때 warning 발생
1>c:\users\xxx\documents\visual studio 2008\projects\mbcs_wbcs1\mbcs_wbcs1\mbcs_wbcs1.cpp(1) : warning C4005: 'UNICODE' : macro redefinition
1> command-line arguments : see previous definition of 'UNICODE'
1>c:\users\xxx\documents\visual studio 2008\projects\mbcs_wbcs1\mbcs_wbcs1\mbcs_wbcs1.cpp(2) : warning C4005: '_UNICODE' : macro redefinition
1> command-line arguments : see previous definition of '_UNICODE'
2) MBCS 기반으로 컴파일 하는 방법
a. 설정창에서 UNICODE, _UNICODE 를 지움 - Inherit from parent or project defaults 체크박스 해제
b. #undef 지시자를 통해 설정 값을 지움
#undef _UNICODE
#undef UNICODE
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
...
4. MBCS와 WBCS를 동시 지원하기 위한 함수들
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int _tmain(int argc, TCHAR* argv[])
{
LPTSTR str1 = _T("MBCS or WBCS 1");
TCHAR str2[] = _T("MBCS or WBCS 2");
TCHAR str3[100];
TCHAR str4[50];
LPCTSTR pStr = str1;
_tprintf(_T("string size: %d \n"), sizeof(str2));
_tprintf(_T("string length: %d \n"), _tcslen(pStr));
_fputts(_T("Input String 1: "), stdout);
_tscanf(_T("%s"), str3);
_fputts(_T("Input String 2: "), stdout);
_tscanf(_T("%s"), str4);
_tcscat(str3, str4);
_tprintf(_T("String1 + String2: %s \n"), str3);
return 0;
}
string size: 30
string length: 14
Input String 1: Hello
Input String 2: World
String1 + String2: HelloWorld
'컴&프로그래밍 > System Programming' 카테고리의 다른 글
1. 컴퓨터 구조에 대한 첫 번째 이야기 (0) | 2014.12.28 |
---|