World of Character Set
출처 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를 가리게 되는 것이다. 원리는 코드를 보면 이해할 수 있다. 이런 코드 말고 함수자체도 WBCS와 DBCS를 구분하게 해주는 코드가 아래에 있다.
#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 |