World of Character Set

C & C++ 관련 : 2007. 10. 20. 15:46
반응형

출처 http://designe.x-y.net/tt/48

World of Character Set

1. Single Byte Character Set :: 한글자가 1byte로 설정되어 있다.    Ex)ASCII CODE

2. Double(Multi) Byte Character Set :: 경우에 따라 1byte, 2byte로 나뉜다.

DBCS의 장점이라고 할 수 있는 영어는 1byte로 표현된다는 것.. 하지만 이것이 큰 단점이 될 수가 있다.

 DBCS의 단점을 나타내주는 SOURCE

#include <stdio.h>

#include <windows.h>

 

bool DBCSReverse(char *);

void main()

{

        char msg[] = "sjdkd만ㅇfskd";

        char* pmsg = msg;

 

        while(*pmsg){

               printf("%s\n", pmsg);

 

               if(IsDBCSLeadByte(*pmsg))

                       pmsg += 2;

               else

                       pmsg += 1;

               //BOOL IsDBCSLeadByte(BYTE TestChar) :: TestChar가나타내는값이byte문자의첫번째바이트라면TRUE

        }

        pmsg = msg;

 

        DBCSReverse(pmsg);

 

        while(*pmsg){

               printf("%s\n", pmsg);

 

               if(IsDBCSLeadByte(*pmsg))

                       pmsg += 2;

               else

                       pmsg += 1;

               //BOOL IsDBCSLeadByte(BYTE TestChar) :: TestChar가나타내는값이byte문자의첫번째바이트라면TRUE

        }

 

       

}

bool DBCSReverse(char *p){

//      int strLength = strlen(p);

        int  left, right, i;

        char TempOneByte, TempTwoByte[2];

        short DBCSConfirmLeft, DBCSConfirmRight;

        left = 0;

        right = strlen(p)-1;

 

        while(right > left){

               DBCSConfirmLeft = IsDBCSLeadByte(*(p+left));

               DBCSConfirmRight = IsDBCSLeadByte(*(p+right));

               if(DBCSConfirmRight)

                       right--;

 

               printf("%c %c\n", *(p+left), *(p+right));

 

               switch (DBCSConfirmLeft + DBCSConfirmRight){ // change

                       case 2://둘다2byte의경우

                              for(i=0; i<2; i++){

                                      TempTwoByte[i] = *(p+left+i);

                                      *(p+left+i) = *(p+right+i);

                                      *(p+right+i) = TempTwoByte[i];

                              }

                              left++;

                              break;

                       case 1://하나만1byte의경우

                              if(DBCSConfirmLeft){//left

                                      for(i=0; i<2; i++)

                                             TempTwoByte[i] = *(p+left+i);

                                      *(p+left) = *(p+right); // 오른쪽자료를왼쪽자료로치환

                                      while((p+left+i) != (p+right)){

                                             *(p+left+i-1) = *(p+left+i);

                                             i++;

                                      }

                                      right--; //바꿔질오른쪽자료가2byte가될것이므로,

                                      for(i=0; i<2; i++)

                                             *(p+right+i) = TempTwoByte[i];

 

                              }else{//right

                                      for(i=0; i<2; i++)

                                             TempTwoByte[i] = *(p+right+i);

                                      *(p+right+1) = *(p+left);

                                      i--;

                                      while((p+right-i) != (p+left)){

                                             *(p+right-i+1) = *(p+right-i);

                                             i++;

                                      }

                                      for(i=0; i<2; i++)

                                             *(p+left+i) = TempTwoByte[i];

 

                                      right++;

                                      left++;

                              }

                              break;

                       case 0://둘다1byte

                              TempOneByte = *(p+left);

                              *(p+left) = *(p+right);

                              *(p+right) = TempOneByte;

                              break;

               }

               left++;

               right--;

        }

 

        return true;

}

 

3. UNICODE :: Wide byte Character Set - founded by Apple and Xerox in 1988.

Unicode를 써야만 하는 이유 – (Programming Applications For MS Windows – Jeffrey Richter)

1. Enables easy data exchange between languages

2. Allows you to distribute a single binary .exe or DLL file that supports all languages

3. Improves the efficiency of your application

이 유니코드는 한문자를 무조건 2byte로 정해놓았다. NULL문자마저 00000000 00000000으로 표현이 되어 있다. 이렇게 한문자를 2byte로 정해놓음으로써, 첫번째 장점이 드러난다. 언어들간의 변경이 매우 자유롭다는 점이다. 저 위의 DBCS의 소스를 보면 알 수 있듯이, 언어마다 바이트수가 다르게 되면 언어들간의 변경이 꽤 힘들다는 것을 알았다.

뭐 그런거다. 지금은 시대가 많이 지나 유니코드가 컴퓨터 상에서 꽤나 자리가 잡혀있다. 하지만 아직도 DBCS가 쓰이는 곳이 많기에 -_ -ㅋㅋ MS에서 특단의 조치를 TCHAR.h.라는 파일에 정의해둔 코드가 있다.(실제로 무지막지하게 길다만, 여기선 생략하기로 한다.)

#ifdef UNICODE

        typedef WCHAR TCHAR; // WCHAR(Wide Character) :: wchar_t가자료형의원형이고, 실제로유니코드로표현하기위해ANSI에정의되어있다.

        typedef LPWSTR LPTSTR; // LPWSTR(Long Pointer Wide String)

        typedef LPCWSTR LPCTSTR; // LPCWSTR(Long Pointer Const Wide String)

#else

        typedef CHAR TCHAR;

        typedef LPSTR LPTSTR;

        typedef LPCSTR LPCTSTR;

#endif

 

#define _T(x) __T(x)

#define _TEXT(X) __T(x)

 

#ifdef _UNICODE

        #define __T(x) L##x // ##은앞의문자와뒤의문자를합쳐주는역할을한다. 실제유니코드를표현하기위해선문자열앞에L을붙여야한다.

#else

        #define __T(x) x

#endif

위의 코드를 보면 알 수 있듯이, UNICODE _UNICODE가 정의된 경우와 정의되어있지 않은 경우로 구분하여 DBCS WBCS를 가리게 되는 것이다. 원리는 코드를 보면 이해할 수 있다. 이런 코드 말고 함수자체도 WBCSDBCS를 구분하게 해주는 코드가 아래에 있다.

#ifdef _UNICODE

        #define _tmain wmain

        #define _tcslen _wcslen

        .

        .

#else

        #define _tamin main

        #define _tcslen _strlen

        .

        .

#endif

 위의 코드를 보면 알 수 있듯이, 문자열 조작함수 말고도 main 함수 또한 유니코드를 지원하기 위해 구분해놓은 것을 볼 수 있다. 실제로 유니코드 기반에서는 main이 아닌 wmain을 가장 먼저 호출하게 된다. :>

 

4. 그 외의 Character Set (UTF-8) :: Unicode Transformation Format-8

, 유니코드에서 정의한 문자 집합을 8비트 문자열 스트림으로 표현하는 것이다.

UTF-8은 언어들간의 우선순위를 정해 1byte, 2byte, 3byte, 4byte로 나누어 저장한다. 이것이 특징이다. 참고로 우리나라 언어는 3byte에 속한다.ㅜㅜ 일본어도 마찬가지[!]

 아래는  UTF-8 MBCS(Multi Byte Character Set)으로 탈바꿈하는 소스이다. J

#include <windows.h>

#include <fstream>

#include <iostream>

#include <tchar.h>

using namespace std;

 

int UTF8ToMultiByte(const char* msg, char** MultiByte){

        wchar_t *WideChar;

        int  size = strlen(msg);

        int WideCharSize, MultiByteSize;

 

        cout << "UTF8 ::" << msg << endl;

 

        WideCharSize = MultiByteToWideChar(CP_UTF8, 0, msg, -1, NULL, NULL);

        WideChar = new wchar_t[WideCharSize];

        MultiByteToWideChar(CP_UTF8, 0, msg, -1, WideChar, WideCharSize);

 

        MultiByteSize = WideCharToMultiByte(CP_ACP, 0, WideChar, -1, 0, 0, 0, 0);

        *MultiByte = new char[MultiByteSize];

        WideCharToMultiByte(CP_ACP, 0, WideChar, -1, *MultiByte, MultiByteSize, NULL, NULL);

 

        delete []WideChar;

 

        return MultiByteSize;

}

 

bool WriteAnsiFile(char* AnsiContent){

        ofstream out;

 

        out.open("AnsiOUTPUT.txt");

        out << AnsiContent;

        out.close();

 

        delete AnsiContent;

        return true;

}

 

int main()

{

        int i=0, AnsiMultiByteSize;

        char UTFString[1000];

        char *PUTFString = UTFString;

        char *AnsiString;

        ifstream in;

 

        in.open("utf.txt");

        in.seekg(3L, ios_base::beg);

 

        if(!in.is_open()){

               cout << "파일을열수없습니다." << endl;

               in.close();

               return 0;

        }

 

        while(in.get(UTFString[i]))

               i++;

        UTFString[i] = NULL;

        in.close();

 

        AnsiMultiByteSize = UTF8ToMultiByte(PUTFString, &AnsiString);

        cout << "size :: "<< AnsiMultiByteSize << endl;

        cout << "content :: " << AnsiString << endl;

 

        WriteAnsiFile(AnsiString);

        return 0;

}

 , 이것말고도 컴퓨터세상에는 Character Set이 정말 많이 존재한다. 온라인 세계에서의 Character Set은 나라마다 언어가 다르기 때문에, 이렇게 모두 통일 시켜 줄 수 있는 효율적인 Character Set이 꼭 필요하다. 앞으로 이런 언어 포맷들이 점점 더 발전하여 정말 쓰기 좋고 평등한 Character Set이 만들어 졌으면 하는 바램이다. J

반응형

'C & C++ 관련' 카테고리의 다른 글

Character Set과 Font  (0) 2007.10.20
Volatile  (0) 2007.09.16
포인터, 배열  (0) 2007.08.12
Posted by Real_G