'WBCS'에 해당되는 글 1건

  1. 2010.05.16 Character Sets 3

Character Sets

Programming 2010. 5. 16. 14:27

  Character Sets(문자 집합)이란 약속된 문자의 표현 방법으로 어떠한 코드로 저장할 것인가에 대한 정의를 의미한다.


1. SBCS, Single Btye Character Set  (ASCII CODE )
  미국에서 표준화가된 코드로서 26개의 대,소 알파벳과 몇몇 확장 문자 및 기호를 포함해서 총 128개의 문자(확장되어 최대 256개)가 정의 되어 있다.  숫자 65를 문자 A에, 97를 a에... 등등 숫자를 문자에 맵핑시켜서 문자를 표현한다.
  ASCII 코드는 8비트를 가지고 문자들을 표현하며, 프로그램에서는 1byte의 크기인 char형를 사용하여 표현을 한다.


사용자 삽입 이미지
(표1) ASCII Code






2. WBCS, Wide Btye Character Set (UNICODE )
  영어가 아닌 다른 나라 국가에서 사용하는 모든 문자들을 표현할 수 있는 문자 코드 체계이다.
16비트면 65,536개를 표현 할 수 있는데, 이 정도면 모든 언어를 충분히 표현 할 수 있다. 각 국가별로 코드 영역이 구분되어 있기 때문에 코드 페이지를 변경할 필요가 없다.
  유니코드는 NULL문자까지 2byte 처리된다.
  - UTF-16 : 한자는 약 55000자 정도로서 옛한자까지 포함하면 16비트로는 부족한데, Surrogate라는 확장 코드를 정의함으로써 더 많은 문자를 표현할 수 있다.  
  - UTF-8 : 가변 길이로서 표현하고자하는 코드에 따라 여러 바이트를 사용하여 합리적으로 설계된 인코딩 방식.

 (참고. 유니코드로 컴파일된 프로그램은 유니코드를 지원하지 않는 윈95/98에서 실행되지 않는다.)

<ANSI 에서 유니코드 지원을 위해서 정의한 표준>
typedef unsigned short  wchar_t;     //char는 1바이트만 할당되지만 wchar_t는 2byte가 할당.

wchar_t  str[ ]= L"ABC";                //※문자 L은 ""문자열을 유니코드 기반으로 표현한다는 의미.

 

(* 헤더파일 포함 관계 :  winnt.h  ⊂  windef.h  ⊂ windows.h )
<winnt.h>

typedef long          LONG;
typedef char         CHAR;
typedef wchar_t    WCHAR;

typedef CHAR*      LPSTR;
typedef CONST CHAR*  LPCSTR;

typedef WCHAR*   LPWSTR;
typedef CONST WCHAR*  LPCWSTR;


ref. >
typedef CHAR      *PCHAR,  *LPSTR, *PSTR;
typedef CONST CHAR      *LPCCH, *LPCSTR, *PCSTR;
typedef WCHAR    *NWPSTR, *LPWSTR, *PWSTR;
typedef CONST WCHAR    *LPCWCH, *LPCWSTR, *PCWSTR;


<windef.h>

#define CONST       const
typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;
typedef int                    BOOL;
typedef float                 FLOAT;


( TextOut함수 정의 )
<WinGDI.h>

WINGDIAPI BOOL   WINAPI TextOutA ( __in HDC hdc, __in int x, __in int y, __in_ecount(c) LPCSTR lpString, __in int c);
WINGDIAPI BOOL   WINAPI TextOutW( __in HDC hdc, __in int x, __in int y, __in_ecount(c) LPCWSTR lpString, __in int c);

#ifdef UNICODE
#define TextOut  TextOutW              //W는 Wide의 약자.
#else
#define TextOut  TextOutA              //A는 ANSI의 약자.
#endif // !UNICODE



<완전한 유니코드를 기반으로한 소스>

#include <stdio.h>
#include <windows.h>
#include "locale.h"

int wmain(int argc, wchar_t* argv[])    
{
      WCHAR str[]=L"한글 출력";
      int len = wcslen(str);

      _wsetlocale(LC_ALL, L"korean");
      wprintf(L"%s \n", str);
      fputws(str, stdout);

      return 0;
}

wmain은 프로그램 실행시 전달되는 문자열을 유니코드기반으로 구성한다는 말이다.
    ex) 실행파일이 main.exe
         c:\> main ABC DEF                 //L"ABC"  L"DEF" 형태의 인자를
  **argv가 가리키게 된다.

wprintf, fputws 등의 함수들을 통해서 유니코드 기반으로 한글을 출력하려면  _wsetlocale(LC_ALL, L"korean") 함수가 호출되어야 한다.  _wsetlocale 는 locale.h 에 정의되어 있다.








3. MBSC, Multi Byte Character Set
  문자를 표현하는데 있어서 동일한 바이트 수를 적용하는 것이 아니라, 다양한 바이트 수를 사용해서 문자를 표현하는 방식이다. 그래서 대부분의 문자들은 1byte로 처리하되(SBCS), 아스키코드에서 정의하지 않는 다른 문자를 표현할 때만 2btye(유니코드)로 처리하게 된다.
  상당히 효율적이지만 프로그램을 구현하는데 있어서 세심한 주의가 필요하다.

▷ MBCS의 문제점

char str[]=“한글입니다”;

for(i=0; i<5; i++)
  fputc (str[i], stdout);                                             // 한글 ←출력값

             //실제 문자열의 길이는 5이지만 한글은 2byte이므로 함수를 10번 호출해야 전부다 출력이 됨.

char str[]="ABC한글"

int len = strlen(str);

printf("배열 크기 %d\n", sizeof(str));                         // 8

printf("문자열 길이 %d\n", len);                               // 7            cf. strlen은 NULL값 제외

               //실제 문자열의 길이는 5이지만 한글은 2byte로 인식하고 있기 때문에 7 출력

모든 문자열을 2byte로 처리하는 WBCS방식을 사용하면 문제점을 해결할 수 있다.








□ WBCS와 MBCS를 동시에 지원하기 위한 매크로
  MBCS기반의 프로그램을 유니코드기반의 프로그램으로 변경하는 경우 문자열앞에 L을 붙이고, 함수들도 모두  변경을 해주어야 한다.
  하지만 UNICODE, _UNICODE 매크로에 의해서 동시에 지원이 가능한 프로그램을 만들 수 있다.

<tchar.h>
  #ifdef UNICODE
    typedef WCHAR     TCHAR;
    typedef LPWSTR    LPTSTR;
    typedef LPCWSTR  LPCTSRT;
  #else
    typedef CHAR      TCHAR;
    typedef LPSTR     LPTSTR;
    typedef LPCSTR   LPCTSTR;
  #endif



#idef _UNICODE
  #define __T(x)    L##x
#else
  #define __T(x)    x
#endif

#define _T(x)       __T(x)
#define _TEXT(x)  __T(x)


#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                                     //ANSI 버전
  #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
//DLL을 만들어서 배포한다고 할때 두 버전의 함수를 제공해야 활용도가 높아진다.


cf.
  이 밖에 운영체제가 제공하는 (API)함수인 lstrlen, lstrcpy, lstrcat, lstrcmp, lstrcmpi, wsprintf 함수가 있다.
  API 함수는 운영체제가 제공하므로 별도의 용량을 차지하지 않고, 이미 메모리에 올라와 있기 때문에 가급적이면 API함수를 사용하는 것이 좋다.
// wsprintf함수는 %f서식을 지원하지 않고, 버퍼 길이가 1024까지만 지원됨. (그래서 _sprintf를 쓰기도 함.)

  #ifdef UNICODE 이라면 WBCS기반의 문자열 저장을 가능하게 하고, UNICODE가 정의되어 있지 않다면 MBCS타입의 문자열로 저장한다.


<WBCS와 MBCS를 모두 지원하는 소스>

      /* 유니코드를 설정해주면 WBCS가 되고, 설정하지 않으면 MBCS가 된다.*/
#include
<stdio.h>
#include <tchar.h>
#include <windows.h>

int _tmain(int argc, TCHAR* argv[])
{
      LPTSTR str1= _T("MBCS 혹은 WBCS 1");
      TCHAR str2[]= _T("MBCS 혹은 WBCS 2");
      TCHAR Input[50];
      LPCTSTR p=str1;

      _tprintf( _T(
"string length %d\n"), _tcslen(p));
      _tprintf( _T("Arr size %d\n"), sizeof(str2));

      _tprintf( _T("Arr size %d\n"), sizeof(Input));          // W 100    M 50

      _tscanf( _T(
"%s"), Input);
      _fputts(Input, stdout);
       return 0;
}

           // W 14                          M 16 ASCII코드에서 정의하지 않는 문자만 2byte
           // W 30 모두2byte취급하니까      M 17                상동




   참고로 유니코드 지원을 위한 프로그램코딩시 유니코드 선언이 헤더파일 전에 선언이 되어야 효과를 볼 수 있다. UNICODE에 선언된 매크로에 따라서 헤더파일의 자료형이 결정되기 때문이다.
  혹은 Visual Studio의 경우 프로젝트 설정(Alt+F7)에서 「Character Set - Use Unicode Character Set」으로 설정해주면 따로 UNICODE선언을 해줄 필요가 없다. 프로젝트 설정에 따라서 D "UNICODE", D "_UNICODE"될 수도 있고, D "_MBCS"가 될 수도 있기때문이다.

  다시 정리하면 WBCS를 위해서 1) #define UNICODE    #define _UNICODE  혹은
                                             2) 프로젝트 설정에서 「Character Set - Use Unicode Character Set」으로 설정.




<참고문헌>
김상형, 윈도우즈 API정복.
윤성우, 뇌를 자극하는 윈도우즈 시스템 프로그래밍.

Posted by 넷지
,