How to Programming by Unicode in windows programming - 2

자, 저번시간에 멀티바이트와 유니코드의 차이를 알았아보았다. 사실 엄격히 말하면 유니코드 조차 멀티바이트긴 하지만 일반적으로 ASCII CODE를 멀티바이트, 유니코드를 유니코드라 한다.

그렇다면 아까의 그 비주얼 스튜디오 2010에서 유니코드로 윈도우즈 프로그래밍을 할수 있는 두번째 방법을 소개 하겠다. 개념은 그리 어렵지 않다.

 그저 멀티바이트 즉, ASCII CODE가 아닌  UNICODE를 사용하면된다.

하지만 방법은 막 어렵지는 않지만 간단하지만은 않다. 왜냐하면, 이 C++이 만들어 질땐 ASCII CODE를 전제로 만들어져 기본적인 명령어는 대부분 ASCII CODE를 기반으로 만들어 졌기때문에 그것을 요리해서 UNICODE도 사용할 수 있도록 변경해야 한다. 문자열이 들어가는 곳이라면 대부분의 코드를 손을 보아야한다. 따라서 ASCII CODE, 즉 일반적인 C에 적응되어 있는 분들은 문자열이 나온다면 긴장을 해야 할것이다.
물론, C++에서 막 문법을 떄고 오신분들이라면 우선 여기에 먼저 적응해지면 되긴 하겠지만 그래도 윈도우즈 프로그래밍에서는 char 가 직접적으로는 절대 안쓰인다고 생각해야한다.

 자, 그럼 어떤걸 쓰느냐?
char는 TCHAR로 사용한다. TCHAR의 정의를 보면
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif

만약, UNICODE를 사용한다면, wchar_t형의 TCHAR를 사용하고 유니코드가 아니면 그냥 char를 사용할께용. 이라는 뜻이다. 그렇다면 wchar_t는 무엇인가? 음... int는 정수형을 담기위한 자료 저장 범위를 지정하기 위한 "자료형"이다. 그렇다면 UNICODE를 위한 저장 크기를 제한한 자료형정도가 되겠다. 정확히 말하면 저거슨 unsigned short로 정의 되어있다.(for UTF-16)
 사실 일반 멀티바이트라면 char를 사용하고 유니코드라면 wchar_t의 자료형을 사용하면 된다. 하지만 xp이후 유니코드가 대세가 되어가고 있고 마소또한 유니코드를 권장하고 있다.

또 몇개의 자료형을 더 찾아보자면

TCHAR : char
LPSTR : char *
LPCSTR : const char*
LPWSTR : wchar_t*
LPCWSTR : const wchar_t*
LPCTSTR : const wchar_t * || const char*

이렇게 있겠는데 음.. 헝가리언 명명법이라고는 알고 있을란지... 아무튼 이름 붙이는 방법이다. 그 이름 붙이는 방법중 약어를 쓰는경우가 있는데 STR은 딱봐도 string이라는거 알겠고 다른 약어들을 대충 찾아본다면

W : Wide char (2바이트를 의미. 대충 유니코드따라잡기용 ASCII Code라 생각하면 됨)
T : unicode || ASCII
C : constant
LP : long pointer
STR : string자료형

그리고 이 유니코드를 지원하는 문자열함수도 따로 있으니 아래의 함수들을 이용하면 된다.
strlen lstrlen
strcpy lstrcpy
strcat lstrcat
strcmp lstrcmp
sprintf wsprintf


음.. 이제 코드만 짜보면 되겠구나 :)
자, 그렇다면 코드는... 다음 이시간에 계속!! 으흐흐흐흐
How to coding by UNICODE in Visual Studio 2010. 

이번학기에 비주얼 프로그래밍 수업을 들으면서..(사실은 뭐 그의 MFC수업이었지만)
기초적인 Windows API에 대해 '맛'을 봤었다.
사실, 이번학기 시작전에 WINDOWS API책을 살짝 훑어보고 시작한지라 공부를 하지 않고도 그럭저럭 학점이 잘 나오리라 생각한다.

하지만, 수업을 듣던중 가장 난감했던 것은. 바로 유니코드.
난 수업시간에 내 노트북을 갖고 다니면서 프로그래밍을 했다.
하지만 계속해서 유니코드때문에 막혔다. 첫번째 시간은 코드를 그대로 쳤으나 코드가 돌아가지 않았다.
아예 해결방법을 찾지못해 하루정도 내내 해결방안을 찾았던것 같다.

일단 해결방법 1
Alt + F7을 누르거나 메뉴에서 (프로젝트)- > (속성) 으로 들어가
왼쪽 프레임에서 (구성 속성) -> (일반)을 클릭하고
오른쪽 프레임에서 아래 문자집합 에 있는 (유니코드 문자 집합 사용)을 (멀티바이트 문자 집합 사용)으로 해준다면 왠만큼 프로그래밈이 이 전 비주얼 스튜디오 에서 코딩하는것 처럼 비슷하게 돌아간다.

하지만, 이건 약간 룰 위반이다.
우선 멀티바이트와 유니코드를 이해해야 한다.
멀티바이트를 이해하기 위해선 아스키 코드에 대해서도 알아야한다.
ASCII CODE란 만약 이걸 보는 이들은 아마도 알고 있겠지만,
컴퓨터는 문자를 인식하지 못한다. 1과 0으로 밖에 인식을 하지 못하기 때문에 인간은 그 문자를 일단 10진수 숫자와 16진수 숫자와 매치시켜 놓는다. 예를들어, 숫자가 73이면 16진수로는 0x4C고 문자는 L 이 된다. 
 이 모든걸 결정한 곳은 어느 말을 쓰는 나라 일까? 바로 미쿡. 따라서 모든 ASCII CODE는 영어로만 이루어져 있다. 사실 ASCII 라는 말은 American Standard Code for Information Interchange의 약자다. 미국 표준이란 소리지. 걔네들이 한국어나 따른 나라 언어 알게 뭐가 있었겠어?
 아무튼 그렇게 10진수와 16진수로 옮겨놓으면 2진수로 만드는건 뭐 식은죽을 그냥 앉아서 천천히 TV보면서 먹는 그런 느낌이 되어버렸지. 그리고
 부호를 포함한 1 Byte즉 8 bit의 2진수로 나타낼수 있는 수는 0000000 부터 1111111 까지. 즉 0부터 127까지다.
알파벳은 총 몇개? 어이어이 세지 말고 ㅋㅋㅋ 26개다. A~Z까지 26개고 음... 그래 대소문자 다 합쳐봐야 52개 에다가... 음.. 그래 숫자도 넣어두면 편하겠찌 그래서 숫자도 넣고. 음.. 또 뭐 없을까? 그래 따옴표하고 구두점하고 수학기호하고 뭐 그런것들좀 집어넣어서 채우다 채우다 좀 남아서 비트들을 활용하여 (그래픽 문자)도 모자라 (제어문자)까지 꽉꽉 채워 넣었다 .제어문자란 음.. DEL키라던가 Space라던가 ESC라던가 그런거 있잖아. 아 그런 공간 좀 남으면 한글이나 넣어줄것이지! 라고 말하고 싶지만 사실 인접 국가. 미국에서 자주사용되는 스폐인어 고유 글자조차 부호없는 1byte(ASCII CODE Extended)에 겨우 포함이 될 정도다.

 자, 이제 아스키코드란걸 조금은 이해를 하겠나? 음... ASCII CODE가 궁금하다면 http://ko.wikipedia.org/wiki/Ascii
위키피디아를 찾아보아도 좋음 :)


자, 이제 ASCII CODE란 걸 왠만큼 알았으니 멀티바이트로 넘어가 보자. 그럼 멀티 바이트란 무엇인가?
바로 이 ASCII CODE는 잘 해봐야 1Byte 인데 왜 싱글 바이트가 아닌 멀티 바이트인가?
 즉슨, 위 에서 언급했던대로 Signed 1byte안에는 only english다. 뭐, 숫자나 뭐그런거 말고 다른 나라의 언어는 없다는 이야기이다. 그리고 unsigned는 그외 프랑스, 스페인, 따깔, 더치어등 잉글리시와 비슷한 언어들만 확장형으로 넣어두고 나머지는 표그리기나 그림그리용으로 채워 넣었다.
 그럼 이제 비주얼스튜디오에서 멀티바이트로 하고 hello world 코딩을 해보자. 아, 영어말고 printf("헬로 월드"); 요롷게 당당하게 한국어로 해보자. 출력은 어떻게 나오는가? 한국어로 나오지 않는가?! 와우. 분명 ASCII CODE에는 영어 밖에 없다. 미국 표준이므로. 하지만 어떻게 한글이 나오지? 물론 개중에는 한글이 지원하지 않아 이상한 상형문자들이 나오는 경우가 있다. 그 이유는 나중에 점차점차 알아가도록 하고. 어찌되었든 한국어가 나온다. 그 이유가 멀티바이트에 있다. 이 문자를 인식할때 싱글바이트, 즉 1Byte로만 인식을 하면 영어만 인식을 한다. 왜냐? 1Byte안에 영어, 한국어, 중국어, 일본어 같은 것들을 모두 넣다보면 그 옛날 꼬물 컴퓨터를 쓸때 만들어진 표준으로써는 그당시 현실에 너무 안맞기 때문이다. 그렇게 몇년을 쓰다가 그걸 또 2Byte로 넘기기엔 표준이 송두리채 바뀌기가 쉽지 않았다. 따라서 하나의 대안을 제시한다.
1Byte를 두개 해서 문자를 표현하자고!!!
영어를 할땐 1Byte만 하면 되고 만약 영어이외의 한국어나 일어, 한자를 표현할때는 1Byte 여러개를 붙여 문자를 표현하기로 한다. 그 것이 ISO-2200(ISO-2200-KR, ISO-2200-JP, ISO-2200-CN) 에 정의 되어 있는 멀티바이트 문자열이다. 뭐 조금 자세히 들여다 본다면 그 1byte의 21-7E를 2개 이어붙여 94*94=8836개의 글자를 표현할수 있다. 좀더 자세히들어가 유닉스쪽 얘기를 한다면 유닉스에서는 그 표준이 약간다른데(EUC:Extended Unix Code로 EUC-KR, EUC-JP, EUC-CN으로 표기한다.) 두개의 바이트를 이어붙이는게 A1-FE 까지라는것을 제외하면 표현할수 있는 글자수도 같아 뭐 비슷비슷하게 사용할수 있다.

자, 이제 멀티바이트에 대해 약간이나마 감이 좀 잡히나? 간단히 말해 ASCII CODE 1Byte를 두개이상 붙여만들었기떄문에 멀티바이트라고 한다.


그렇다면 유니코드란 무엇인가?
ASCII는 영어일경우는 1Byte, 다른나라 언어는 +a를 하게된다. 그렇다면 어떤 일이 벌어지는가?
다른 나라 언어에 +a를 한다고 해도, 만약 한국어로 된 문장을 일본어로 해석하게 되면 어떻게 되겠는가? 이런 연유로 가끔씩 페이지를 돌아다닐때 홈페이지 전체가 상형문자로 덮혀있는 페이지를 발견하게 되는것이다. 즉, 글자가 깨진다고 하는것이다.

 자, 이것을 위해 유니코드가 태어났다. 이 American놈들의 지저분한 Standard를 꺠고 Universial한 Code를 만들어 냈다. 그것이 바로 유니코드다. 이 유니코드는 두개를 이어 붙이는게 아니라 처음부터 2Byte를 할당하여 파일 하나에 컴퓨터로 표현하는 세상 모든 문자를 담았다. 하지만 아직은 인터넷계의 주류를 담고 있는 영어에 뭔가 불리하지 않겠는가? 쓰지도 않을 일본어때문에 굳이 용량을 키우면 뭔가 좀 거시기 하지 않겠는가?라는 생각이 들어 이 유니코드도 3가지로 나눠져 있다. 그거슨 UTF-8, UTF-16, UTF-32 로 나눈다.
UTF-8이 그 ASCII CODE와 같이 8비트만을 이용한 글자. UTF-16은 16비트를 사용하고 UTF-32는 32비트를 사용하여 글자를 나타낸다. 하지만 이것은 말했듯이 ASCII CODE처럼 두개의 1 Byte를 이어붙이는 것이 아니라 순수하게 1byte면 1byte, 2byte면 2 byte를 사용한다. 그래서 인터넷보면 UTF-8 인터넷 주소만 이용 뭐 이런게 있는데 즉, 한글주소나 뭐그런거 다 빼고 영어만 쓰겠음. 뭐 그런거다.

자, 이렇게 ASCII CODE와 UNICODE는 그 근본적으로 차이가 있다. 따라서 개발자는 죽어나간다. 표준이 여러개라...

블로깅이 너무 길어 졌으므로 다음 내용은 다음 포스팅에 계~~ 속. (아마도 실질적인 첫, Windows Programming에서 기본적인 Windows Frame의 UNICODE 의 Code가 되지 않을까 싶다. 즉 방법2는 .... 다음 회에 계속 이라는 거지 ㅋㅋ)

'Programming > Visual C++' 카테고리의 다른 글

출력3. DrawText  (0) 2011.06.28
출력2. WM_Paint  (0) 2011.06.28
출력1. TextOut  (0) 2011.06.28
How to Programming by Unicode in windows programming - 3  (1) 2011.06.25
윈도우즈 프로그래밍에서 유니코드로 코딩법 2  (1) 2011.06.25
 안드로이드공부를 하기 위해서 도서관에 있는 책들을 속독 음.... 정확히 말하면 발췌독으로 10권이상 봤다. 그러니까 내가 필요한 부분은 정독을 하고 그 외의 부분은 대충 무언가를 찾기 위해 주루룩 읽었다는 소리지.
 그러면서 느낀건. 아... 외국책을 찾아봐야 하나? 라는 생각이 들었다. 요세 아이패드로 C++ the Complete Reference 4th Ed 라는 책을 원서로 보고 있는데 우리나라의 윤성우씨 만큼이나 잘 만들었다. 끝까지 읽어봐야 하겠지만, 윤성우씨만큼 친근감이 있는 서체는 아니지만 그래도 필요한것과 알아야할것들의 순서를 잘 배열해서 책을 쓰셨다.
 공부를 잘하고 못하는것. 그것은 무언가를 배울때 무언가를 할때 포인트를 잡느냐 못잡느냐의 차이다. 한정된 시간속에서 뭐가 중요하고 뭐가 중요하지 않은지를 정확히 이해하기 빠르게 알려주는 선생이 좋은 선생이 된다. 그것에 실패해서 살아생전 아인슈타인은 특수상대성 이론으로는 노벨상을 못타지 않았는가?!
 아무튼, 아직 우리나라 책중에 읽을만한 안드로이드 책은 없다. 제대로 구성된 책도 없다. 커리큘럼을 어디서부터 어떻게 해야되는지 모르는 책들이 너무 많다. 읽어 본 책들중 70%가 비슷한 구성으로 되어있다. 그중 특이하다 싶은건 어도비 플레쉬로 만드는 안드로이드 프로그래밍이랑 인사이드 안드로이드. 그리고 아이폰이랑 크로스 플랫폼을 만들기위한 책.
 다른 책들은 너무 피상적인것들이 많다. 물론, 그렇게 코드를 보고 따라하는것이 시작이지만, 시작만 써놓은 책들이 대부분이다. 만약 원하는 것 이 있다면, 시작은 그렇게 하되 그 원리를, 주요 안드로이드 소스를 분석해서 그것을 응용할수 있게 해줘야 되는게 아닐까? 그걸 조금이나마 한 책이 아이폰 안드로이드 크로스 플랫폼에 대한 책이었다. 그림그리기 프로그램 프로젝트 하나만 잇어서 뭔가 좀 아쉽긴 했지만, 그런식으로 안드로이드 전체를 소개한다면 반드시 사고 싶은 책중 하나.
 
 만약 지금 시중에 나와 있는 책으로 안드로이드를 공부하자 하면, 리눅스를 알아야 하고, O/S를 이해해야하며, 커널과 기본적인 O/S기반 프로그램 및 자바의 클래스 구조, 패키지의 개념, 그리고 xml까지 알아야 한다. 어떤 책에서는 xml을 사용하지 않고 자바코드만으로 구현이 가능하다며 "소개"하면서 코드를 비교하는 것까지 해놓은걸 봤지만 그 다음 부턴 xml과 연동해서 설명한다. 물론, 그게 빠른 길이긴 하지만 그렇게 되면 원리의 시점에서 보면 조금 안타까운 면이 없지 않다. 사실 안드로이드 프로그래밍에서 xml을 주요 프로그래밍 소스로 선택한다면 음.. 뭐랄까 코드 해석 할때도 그렇고 짤때도 그렇고 여기저기 옮겨다니면서 해야되기때문에 더 복잡해 진다고나 할까? 아직 원리를 배우는 입장에서는 말이지... 만약 그걸 다 할수 있게 된 후에 xml을 사용한 프로그래밍을 추가한다면, 더욱 효과적이게 되지 않을까?
 
그리고 내가 정작 필요한 image 아답터를 만드는 방법이나 이런걸 소개한 책은 없었다. 게다가 4권정도는 그림 파일을 불러올 때 안드로이드에서 제공한 갤러리에서 string배열을 이용한 아답타 소개만을 코드로 보여주고 소개했을뿐이었다. SD card제어부분도 상당히 약한 게 많았고 말이지. 이래서 안드로이드를 공부하려면 인터넷을 이용하고 스터디로 모여서 하라! 고 하는게 아닐까? 음.. 아무튼 그럼 기말끝나고는 원서들좀 뒤적거려봐야겠다.

'Android' 카테고리의 다른 글

안드로이드 DatePickerDialog 년도 제한  (0) 2015.05.27
전치암호는 단순히 평문의 문자순서를 정해진 순서에 따라 재 배열한것. 
만약 모자라는 부분은 임의이 문자로 대치한다.

정해진 순서가 있기때문에 키값을 정해 순열을 정할수 있다.
예를들어 1 2 3 4 5 6 7 이란 순서를
3 4 5 7 1 6 4 2 이렇게 뒤집는다는 소리다.
만약 총 글자의 수가 7로 나누어 떨어지지 않는다면 빈 자리가 있을수 있기때문에 그 자리를 임의의 문자나 무언가로 대치한다.

평문 : My name is Peace

암호문 :  aeMmnysPa e ixxxcxxe 

복호문 : My name is Peace

C++ 코드

#define BLOCK_SIZE 7

#include <iostream>


using namespace std;


int main()

{

    int i,j,size, block_num;

    int key[64]={3,5,7,1,6,4,2};

    char p_text[64], c_text[64],d_text[64];

    

    cout<<"평문 입력 : ";

    gets(p_text);

    

    size=strlen(p_text);

    

    if(size%BLOCK_SIZE>0)

    {

        block_num = strlen(p_text) / BLOCK_SIZE +1;

        

        for(i=strlen(p_text);i<block_num*BLOCK_SIZE;i++)

            p_text[i]='x';

    }

    else

        block_num = strlen(p_text) /BLOCK_SIZE;

    

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

        for(j=0;j<BLOCK_SIZE;j++)

            c_text[i*BLOCK_SIZE+j] = p_text[(key[j]-1)+i*BLOCK_SIZE];

    

    cout<<"암호문 : ";

    for(i=0;i<block_num*BLOCK_SIZE;i++)

        cout<<c_text[i];

    cout<<endl;

    

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

        for(j=0;j<BLOCK_SIZE;j++)

            d_text[(key[j]-1)+i*BLOCK_SIZE] = c_text[i*BLOCK_SIZE+j];

    

    cout<<"복호문 : ";

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

        cout<<d_text[i];

    cout<<endl;


}

 

'정보 보안' 카테고리의 다른 글

Vigenere 암호(Vigenere cipher)  (0) 2011.05.21
단일 대치 암호(mono-alphabetic substitution cipher)  (0) 2011.05.21
시저 암호(Caesar cipher)  (0) 2011.05.21
다중 문자 대치 암호로써 하나의 펴문 문자가 여러 개의 암호로 대치 될 수 있다.
대치 될때 그 순서에 따라 즉, 비밀키 열(stream)에 의해 달라진다.
프랑스의 암호학자 B. Vigenere가 고안하여 이런 이름이 붙여 졌다.

이 암호 방식은 대치표의 개수를 d라 하면 다중 대치 암호방식은 주기 d를 갖는다. 다중 대치 암호에서 비밀키는 k1, k2 부터 kd까지 있고 평문 m1, m2부터 md, md+1, md+2 이렇게 있으면 암호 키열에 따라 d의 주기로 이 키열의 암호문이 변경된다.

평문 :: My name is Peace
키 값 :: diffcode 
암호문 :: 

Vg scah la Agofi
복문 :: My name is Peace

  

C++ 코드


#include <iostream>

#include <cstring>


using namespace std;


int main()

{

    int i=0,j=0,key_size=0, str_size=0, select=0;

    char str[50] ={0,};

    char key[16]={0,};

    

    cout<<"평문 또는 암호문을 입력하시오 "<<endl;

    gets(str);

    

    

    cout<<"암호문은 1 복호는 2 : ";

    cin>>select;

    

    fflush(stdin);

    

    cout<<" 값입력 : ";

    cin>>key;

    

    

    str_size= strlen(str);

    key_size= strlen(key);

    

        

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

    {

        j=i % key_size;

        

        if(select==1){

        

        if((str[i]>='a')&&(str[i]<='z'))

        {

            str[i]-='a';

            key[j]-='a';

            

            if((str[i]+key[j]) <0)

                str[i]+=26;

            

            str[i] =(str[i]+key[j])%26;

            str[i]+='a';

            key[j]+='a';

        }

        

        if((str[i] >='A')&&(str[i]<='Z'))

        {

            str[i]-='A';

            key[j]-='A';

            

            if((str[i]+key[j])<0)

                str[i]+=26;

            

            str[i]=(str[i]+key[j])%26;

            str[i]+='A';

            key[j]+='A';

        }

        }

           

        if(select == 2)

        {

            

            if((str[i]>='a')&&(str[i]<='z'))

            {

                str[i]-='a';

                key[j]-='a';

                

                if((str[i]-key[j]) <0)

                    str[i]+=26;

                

                str[i] =(str[i]-key[j])%26;

                str[i]+='a';

                key[j]+='a';

            }

            

            if((str[i] >='A')&&(str[i]<='Z'))

            {

                str[i]-='A';

                key[j]-='A';

                

                if((str[i]-key[j])<0)

                    str[i]+=26;

                

                str[i]=(str[i]-key[j])%26;

                str[i]+='A';

                key[j]+='A';

            }


            

        }

    }

    

    cout<<endl<<"암호화 또는 복호화된 결과 출력 : "<<str<<endl;

    

    return 0;

    

} 

+ Recent posts