본문 바로가기

Windows/_System Programming

Windows에서의 문자셋(Character Sets)

1. 문자셋의 종류와 특성

SBCS(Single Byte Character Set) : 1바이트로 문자를 표현한다. 대표적으로 아스키 코드(ASCII CODE)가 있다.

MBCS(Multi Byte Character Set) : 문자를 표현 하는데 있어서 ASCII CODE 는 1바이트로 그 외에는 2바이트로 처리한다.

WBCS(Wide Byte Character Set) : 모든 문자를 2바이트로 표현한다. 대표적으로 유니코드(UNICODE)가 있다.


2. WBCS 기반 프로그래밍

기본적으로 운영체제에서는 문자열을  MBCS 기반으로 처리한다.

예)

#include <stdio.h>
#include <string.h>

int main()
{
         char str[] = "AB가나";
         int len = strlen(str);
         printf("%d", len);

         return 0;
}

이 코드의 실행 결과에서 MBCS 기반으로 프로그래밍 했을때 생기는 문제점을 알게될 것이다.
(문자열마다 할당 바이트가 다르기 때문에 생기는 문제점)

이러한 문제점의 한 해결책이 WBCS 기반 프로그래밍이다.

WBCS 기반으로 프로그래밍 하기 위해선 SBCS 기반의 함수를 WBCS 기반의 함수로 바꿔줘야 한다.

 SBCS 함수  WBCS 함수
 main  wmain
 char  wchar_t
 "상수"  L"상수"
 strlen   wcslen
 strcpy  wcscpy
 strncpy  wcsncpy
 strcat  wcscat
 strncat  wcsncat
 strcmp  wcscmp
 strncmp  wcsncmp
 printf  wprintf
 scanf  wscanf
 fgets  fgetws
 fputs  fputws
(참고 : wprintf, fputws 와 같은 함수들을 통해서 유니코드 기반으로 한글을 출력하고 싶다면 함수를 호출하기 전에
_wsetlocale(LC_ALL, L"korean");        // #include <locale.h>
_wsetlocale는 프로그램이 실행되는 나라 및 지역에 대한 정보를 설정하는 함수이다.)

WBCS 함수를 사용할때는 파라미터도 모두 유니코드 기반 문자열이어야 한다.

예)

#include <stdio.h>

int wmain(int argc, wchar_t* argv[])
{
       for(int i = 1 ; i < argc; i++)
       {
                wprintf(L"%s", argv[i]);
       }
       return 0;
}



3. MBCS, WBCS 동시지원 프로그래밍

1) Windows에서 정의하고 있는 새로운 자료형 // #include <windows.h>

typedef      char                      CHAR;
typedef      wchar_t                 WCHAR;
 
#define      CONST                  const;

typedef     CHAR*                    LPSTR;
typedef     CONST CHAR*        LPCSTR;

typedef     WCHAR*                 LPWSTR;
typedef     CONST WCHAR*     LPCWSTR;

(Tip : 새로운 자료형을 정의하는 이유 :
1. 선언의 편리성 : typedef unsigned int size_t (긴 문장을 간결하게 대체하며 의미도 강하게 부여된다)
2. 확장의 용이성 : typedef unsigned char STR_LEN -> typedef unsigned int STR_LEN
(한번의 수정으로 STR_LEN 자료형을 쓰는 모든 변수가 char->int 로 확장되었다))


2) MBCS와 WBCS를 동시에 지원하기 위한 매크로

(매크로에 대한 개념 : http://dakuo.tistory.com/~~~)

Windows에서 MBCS와 WBCS를 동시에 수용하는 형태의 프로그램 구현을 위해서 매크로를 정의하고 있다.

#ifdef   UNICODE
     typedef WCHAR         TCHAR;
     typedef LPWSTR        LPTSTR;
     typedef LPCWSTR      LPCTSTR;
#else
     typedef CHAR           TCHAR;
     typedef LPSTR          LPTSTR;
     typedef LPCSTR        LPCTSTR;
#endif

다음은 tchar.h 에 선언내어 있는 내용이다.  // #include <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)


3) MBCS와 WBCS를 동시에 지원하기 위한 함수

tchar.h 에 선언되어 있는 함수이름 매크로이다.

#ifdef _UNICODE 
  #define _tmain      wmain 
  #define _tcslen     wcslen 
  #define _tcscat     wcscat 
  #define _tcscpy    wcscpy 
  #define _tcsncpy  wcsncpy
  #define _tcscmp   wcscmp 
  #define _tcsncmp  wcsncmp
  #define _tprintf      wprintf 
  #define _tscanf     wscanf 
  #define _fgetts      fgetws 
  #define _fputts      fputws
#else
  #define _tmain      main 
  #define _tcslen     strlen 
  #define _tcscat     strcat 
  #define _tcscpy    strcpy 
  #define _tcsncpy  strncpy
  #define _tcscmp   strcmp 
  #define _tcsncmp  strncmp
  #define _tprintf      printf 
  #define _tscanf     scanf 
  #define _fgetts      fgets 
  #define _fputts      fputs
#endif


4) 실제 적용( 위에 1), 2), 3)의 선언들을 잘 참조하면서 하나씩 순서대로 적용해본다)

TCHAR str[5];

#define UNICODE (유니코드가 정의되어 있다면)
TCHAR str[5];  ->  WCHAR str[5];  ->  wchar_t str[5];

유니코드가 정의되어 있지 않다면
TCHAR str[5];  ->  CHAR str[5];    ->  char str[5];

_T("DAKUO");

_T("DAKUO");  -->  __T("DAKUO");

#define _UNICODE
__T("DAKUO");  -->  L"DAKUO";

유니코드가 정의되어 있지 않다면
__T("DAKUO");  -->  "DAKUO";

_tmain

#define _UNICODE
_tmain  -->  wmain

유니코드가 정의되어 있지 않다면
_tmain  -->  main


예)

#define UNICODE       // WBCS 지원, 만약 이부분을 주석처리할 경우 MBCS 지원
#define _UNICODE     // WBCS 지원, 만약 이부분을 주석처리할 경우 MBCS 지원

#include <stdio.h>
#include <windows.h>
#include <tchar.h>

int _tmain(int argc, TCHAR* argv[])
{
        LPTSTR str1 = _T("HACKER");
        TCHAR str2[100] = _T("DAKUO");
        TCHAR str3[20];        

        LPCTSTR pstr = str1;
        
        _tprintf(_T("str1 len = %d \n"), _tcslen(str1));
        _tscanf(_T("%s"), str3);
        
        _tcscat(str2, str3);
        _tprintf(_T("%s\n"), str2);
 
        return 0;
}