Unsigned char -> 유니코드CString

#include <afxconv.h>

 

 

USES_CONVERSION;
CString strTemp;

strTemp = A2W( (char*)cData );

by 꿈꾸는데브맨 | 2011/01/26 23:31 | VC++ | 트랙백 | 덧글(0)

이클립스 실행시 Failed to create the JAVA Virtual Machine err

----------------------------------------------------
 추가내용
----------------------------------------------------
-vm
C:\Program Files\Java\jdk1.6.0_23\bin\javaw.exe
----------------------------------------------------

-startup
plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.1.R36x_v20100810
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
128M                    ==> 256 -> 128  수 정
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
128m                    ==> 256 -> 128 수 정
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m

by 꿈꾸는데브맨 | 2011/01/21 14:29 | ANDROID | 트랙백 | 덧글(0)

UNICODE란??

UNICODE

UCS(Universal Code System)

ISO/IEC 10646-1(Universal Multiple-Octet Coded Character Set)

 

Unicode?

-      전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 제안된 국제적인 문자코드규약

-      사용 중인 플랫폼, 프로그램, 언어에 관계없이 문자마다 고유한 숫자를 제공한다

 

■ 유래

-      미국에서는 32부터 127까지의 숫자를 이용하는 ASCII코드가 있었다. 공간(NULL, BS, CR, ) 32개였고 A 65번이었다. 이 아스키코드는 7비트로 저장이 되는데, 당시 대부분의 컴퓨터는 8비트를 이용하고 있었기에 모든 ASCII코드를 저장할 수 있었을 뿐만 아니라 남는 부분도 있었다.

-      물론 영어만 사용한다면 충분하겠지만 바이트는 8비트로 이루어졌기 때문에, 대부분의 사람들이 128~255는 그들 나름대로 점유해버렸다. IBM-PC OEM Character Set을 가졌고, 다른 나라들은 서로 다른 Character Set 을 가지고 되어서 당시에는 문서교환을 신뢰하기 힘들었다.

-      게다가 아시아의 문자들은 개수만 수만가지가 넘기 때문에 8비트로 도저히 처리할 수가 없었다. 아시아 문자에 대해서는 DBCS(Doucle Byte Character Set)라는 복잡한 시스템이 해결을 한다. 1바이트에 저장하는 문자도 있지만 2바이트에 저장하는 문자도 있었다. 문자열의 바뀜이 빈번해 질수록 혼란감이 가중됐다. 이 때 유니코드가 탄생한다.

-      Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys 및 기타 여러회사에서  유니코드를 채택하였다

 

■ 역사

-      1884 : ISO TC97/SC2 동경회의서 국제 문자코드의 표준화 추진을 위한 Working Group 구성

-      1986 : TC97의 후신인 JTC1에서 각 국에 판(plane) 할당

-      1989 : 요르단 암만회의에서 한중일 한자어에 대한 통합 논의

-      1990 : 한자 통함을 위한 CJK-JRG 구성, 한글 2350자를 기본 다국어 문자판(BMP)에 수록

-      1991 : 유니코드 1.0 ― 프랑스 르노회의에서 미국 유니코드안을 수용, 대폭적인 구조 수정

각 국의 문자판에 관한 논의 배제, KSC-5657의 한글 추가, 한중일 통합한자 수록

-      1992 : 서울회의에서 구조 변경 확정,

한글 완성자 및 새로운 방식의 조합형 한글 구현 방식 추가

옛 한글 완성자(1673) 삭제

-      1993 : 유니코드 1.1 ― 그리스 아테네 회의에서 최종 확정

-      1996 : 유니코드 2.0 11172자의 모든 현대 한글이 포함되었다.

-      1998 : 유니코드 2.1

-      2000 : 유니코드 3.0

-      2001 : 유니코드 3.1 ― 보충언어판이 처음으로 소개되었다.

-      2002 : 유니코드 3.2

-      2003 : 유니코드 4.0

-      2005 : 유니코드 4.1

-      2006 : 유니코드 5.0

 

■ 유니코드 인코딩

-      UCS-2   : ISO/IEC 10646의 용어로 5,536코드를 정의하며, 2바이트로 표현된다.

   1개의 언어판, BMP만이 이에 해당된다.

-      UCS-4   : ISO/IEC 10646의 용어로 4바이트로 표현된다.

   모두 128개의 언어판 그룹(128*256)

-      UTF-7     : 메일 시스템을 통한 전송을 위해 7bits ASCII로 변경, 1bit는 부호코드

-      UTF-8   : 사이즈를 줄이기 위해 영문은 1byte 다른 언어는 2bytes 이상으로 표현

-      UTF-16  : 16비트, 2바이트를 사용하여 모든 언어의 character code를 표현 (UCS-2와 거의 동일)

-      UTF-32  : 32비트, 4바이트로 모든 유니코드 문자를 표현한다.

 

■ 일반 Unicode UTF-8 Unicode

-      일반 유니코드

 : 모든 글자를 2Bytes로 표현한다.

: 전 세계 모든 글자들을 한꺼번에 표현할 수 있다.

: 인터넷에 HTML파일로 올릴 수 없다.

-      UTF-8 유니코드

 : 영문/숫자/기호는 1Byte, 한글과 한자 등은 3Bytes로 표현합니다.

: 전 세계 모든 글자들을 한꺼번에 표현할 수 있다.

: 웹 페이지 작성에 사용할 수 있다.

: 가변 길이므로 영어,유럽어 저장시 공간을 덜 차지한다

 

■ 한글 텍스트 문서를 유니코드로 변환하기

-      이엠에디터(EmEditor)

: 저장 시 EncodingUnicodeUTF-8로 지정한 후 저장

-      메모장(Notepad)

: 저장 시 EncodingUnicodeUTF-8로 지정한 후 저장

-      울트라에디트(Ultraedit)

: 메뉴의 File-Conversions(변환) 에서 ASCII To Unicode 혹은 ASCII To UTF-8을 선택

UNICODE 관련 API

- Windows Data Types for Strings
// Generic types
#ifdef UNICODE
    typedef wchar_t TCHAR;
#else
    typedef unsigned char TCHAR;
#endif
 
typedef TCHAR * LPTSTR, *LPTCH;
 
// 8-bit character specific

typedef unsigned char CHAR;
typedef CHAR *LPSTR, *LPCH;
 
// Unicode specific (wide characters)

typedef unsigned wchar_t WCHAR;
typedef WCHAR *LPWSTR, *LPWCH; 
 

- Conventions for Functions

BOOL SetWindowText(

  HWND hwnd,

  LPCTSTR lpText

);

#ifdef UNICODE

#define SetWindowText SetWindowTextW

#else

#define SetWindowText SetWindowTextA

#endif // !UNICODE

// Windows (ANSI) Prototype

BOOL SetWindowTextA(

  HWND hwnd,

  LPCSTR lpText

);

// Unicode Prototype

BOOL SetWindowTextW(
  HWND hwnd,
  LPCWSTR lpText
);

- Unicode and Character Set Functions

Return
Type

Function

Description

int

GetTextCharset

HDC 현재 글의 Character set 가져온다

Int

GetTextCharsetInfo

HDC 현재 선택된 문자의 Character set 가져온다

BOOL

IsDBCSLeadByte

지정된 문자가 Lead Byte 인지 알아본다

BOOL

IsDBCSLeadByteEx

해당 Code Page 사용하여 지정된 문자가 Lead Byte 인지 알아본다

BOOL

IsTextUnicode

Buffer Unicode형식과의 유사한지 구분한다

int

MultiBYteToWideChar

MultiByte Unicode 변환한다

BOOL

TranslateCharsetInfo

 

int

WideCharToMultiByte

Unicode MultiByte 변환한다

 

- 문자열 조작 함수

일반 함수명

T타입 함수명

기능

strcpy

wcscpy

문자열 복사

strncpy

wcsncpy

특정 길이 문자열 복사

strcat

wcscat

문자열 추가

strstr

wcsstr

문자열 검색

strchr

wcschr

문자 검색

strrchr

wcsrchr

역순 문자 검색

strcmp

wcscmp

문자열 비교

stricmp

_wcsicmp

대소문자 구분 없이 문자열 비교

mkdir

_wmkdir

디렉터리 생성

fopen

_wfopen

파일 열기

 

 

 

 

참고

MSDN                           http://msdn.microsoft.com/

조엘 온 소프트웨어            http://www.joelonsoftware.com/

MonoStyle                                http://tong.nate.com/pktoto/

유니코드 페이지                http://www.kristalinfo.com/K-Lab/unicode/unicode-kr.html/

그 외 다수

by 꿈꾸는데브맨 | 2010/11/03 23:22 | VC++ | 트랙백 | 덧글(0)

유니코드에 관한 고찰...

♧ 유니코드

-싱글바이트와 더블바이트

: strlen을 호출하면 싱글바이트 문자들의 문자열 종결자(제로)배열내 문자들의 수를 리턴한다. 문제는 몇 언어들과 쓰이고 있는 시스템들 (예 : 일본어 kanji)이 싱글바이트가 제공하는 최대 256개의 심볼보다 더 많은 기술을 사용한다는 것이다. 그래서 더블바이트 문자세트는 이런 언어들과 기록시스템을 지원한다. (비주얼 C++런타임 라이브러리 : _mbslen함수)

- 1988년 애플과 제록스 사에 의해 표준화

- 더블바이트 문자세트는 다음 바이트가 같은 문자의 일부인지 새로운 문자인지 구분해야 하는데 유니코드는 그럴 필요가 없어서 CharNext, CharPrev와 같은 함수는 필요가 없다. 또한 16비트 값으로 표현하기 때문에 65000이상의 문자들을 이용할수 있으므로 싱글바이트 문자세트로 256문자들을 이용하는것과는 많은 차이가 난다.

- 현재 29000코드 포인트들이 할당되지 않고 있어서 이것들은 미래의 사용을 위하여 보류된 것이다. (키릴어, 영어, 히브리어, 아라비아어 등등을 표현한다)

- 유티코드를 사용하는 이유

․ 언어들 사이에서 쉬운 데이터로 변환이 가능

․ 모든 언어를 지원하는 싱글 바이너리, .exe 또는 DLL파일의 분배가 가능

․ 애플리케이션의 효율향상

- 윈도우 2000은 유니코드 사용을 근거로 만들어졌다. 즉, 윈도우 함수를 호출하고 그것을 ANSI문자열로 넘기면, 시스템은 처음에 그 문자열을 유니코드로 바꾸고, 그 다음 유니코드 문자열을 운영체제로 넘긴다. 또한 함수로부터 ANSI문자열을 기다린다면, 애플리케이션으로 돌아가기 전에 시스템은 유니코드 문자열을 ANSI문자열로 변환한다. 물론 이런 변환을 수행하기 위해서는 시간과 메모리의 오버헤드가 존재한다.

예를들어, CreateWindowEx를 호출하고 유니코드가 아닌 클래스 이름과 윈도우 캡션을 전달하게 되면, CreateWindowEx는 메모리 블록을 할당해야 하고, 유니코드가 아닌 문자열을 유니코드로 바꿔야 한다. 그리고 그 결과를 할당된 메모리 블록에 저장하고, 유니코드버전 CreateWindowEx를 호출하는 함수를 만들어야 한다. 또한 문자열을 버퍼에 넣는 함수에서는 애플리케이션이 그 문자열을 처리히기 전에 시스템은 반드시 유니코드를 유니코드가 아닌 코드로 바꾸어야 한다. 그러므로 처음부터 유니코드를 사용하는 애플리케이션을 개발함으로써 능률적으로 수행하게 할 수 있다.

- Microsoft Unicode Story

․ 윈도우 2000은 유니코드와 ANSI를 지원한다. 즉 둘 중 하나로 개발할 수 있다.

․ 윈도우 98은 ANSI만 지원하므로 ANSI로만 개발해야 한다.

․ 윈도우 CE는 유니코드만 지원하므로 유니코드로만 개발해야 한다.

- COM : 문자열을 요구하는 모든 COM인터페이스 메소드는 단지 유니코드 문자열만 받도록 되어있다. 왜냐하면 COM은 전형적으로 다른 컴포넌트가 서로 대화할 때 사용되고, 유니코드는 문자열을 전달하는 좋은 방법이기 때문이다. 만일 윈도우 98로 개발하고 COM을 사용한다면 많은 문제가 발생할 것이다.

- 유니코드 소스 작성하는 방법

․ typedef unsigned short wchar_t;

wchar_t szBuffer[100]; 이렇게 버퍼를 생성한다. 물론 strcpy, strcat같은 표준 c런타임 문자열함수는 ASNI문자열만 연산한다. 그래서 그에 대응하는 유니코드함수가 있다.

char* strcat(char*, const char*);

wchar_t* wcscat(schar_t*, const wchar_t*);

이렇게 모든 유니코드 함수는 wcs(wide character string)로 시작한다. 그러므로 str을 wcs로 변경하면 된다.

- CreateWindowExW와 CreateWindowExA함수 프로토타입 비교

․ PCWSTR : 상수 유니코드 문자열 포인터

․ 윈도우 2000에서 CreateWindowExA의 마이크로소프트 소스코드는 단순히 청크(thunking)또는 변환, 즉 ANSI문자열을 유니코드 문자열로 바꾸기 위한 레이어가 된다.

그래서 코드는 바꾼 문자열을 전달하여 CreateWindowExW를 호출한다.

- ANSI와 유니코드를 대비한 애플리케이션 만들기

․ 윈도우 문자열 함수 : lstrcat, lstrcmp, lstrcmpi, lstrcpy, lstrlen

: 이들 함수는 소스 모듈이 컴파일될 때 UNICODE가 정의되었는지에 따라 유니코드 버전 함수나 ANSI버전 함수를 호출하는 매크로로 구현된다. 즉, lstrcat는 lstrcatA와 lstrcatW로 확장될 것이다.

․ 일반적인 데이터타입(TCHAR과 PTSTR과 같은)을 텍스트문자와 문자열로 사용한다.


- 유니코드는 한마디로 말하면 모든 문자를 2byte로 표현하자는 의미이다.

- 98은 전혀 지원하지 않는다.

- CE은 유니코드만 지원한다.

- 2000은 유니코드와 ANSI를 지원한다.

- 미래 os는 유니코드만 지원하게 될 거 같다.

- 그래서 코드를 재 사용할 때 문자열 표현에 문제가 생긴다.

예)char sz[100] : 미래에는 char보다 short int로 컴파일 해야한다.

그래서 지금 코딩할 때 유니코드 버전을 대비해서 미리 코딩하는 기법을 써야한다.

- 유니코드 쓰는 방법 : short int sz[100];

그런데 아직은 전부 다 이렇게 쓸 수가 없다.

- 유니코드를 쓰는 세 가지 관점

① 변수 선언

② 상수 선언

③ 함수 선언

1) 변수 선언

- char나 short int를 쓸 수 없어서 매크로를 만들어 놨다. : TCHAR

이러면 상황에 따라서 두 가지로 컴파일이 된다. 유니코드는 short int로, ansi는 char로 컴파일이 된다. 그러므로 앞으로는 TCHAR을 쓰는 게 좋다.

윈도우 CE에서 작업할 때 기존의 소스를 포팅하려면 char를 전부 수정해줘야 하는 문제가 생긴다.

- 포인터 변수일 경우는 (정수는 문제가 되지 않기 때문에 char *를 말한다) TCHAR*로 써줘야 한다. 그래서 이것도 다음과 같이 매크로로 만들어 놓았다.

- LPCTSTR : 상수형이다. c가 있으면 TCHAR* 상수형이다

- LPTSTR : TCHAR* 버퍼형이다. 즉 배열을 잡아서 써야한다. 그렇지만 LPCTSTR은 상수형이므로 바로 "HOWON"과 같이 쓸 수 있다.

-LPCSTR, LPSTR : 이것들은 T가 없으므로 여전히 char*로만 컴파일이 된다. 그래서 쓰지 않는다.

2) 상수 선언

- 문자열 상수 " "를 말한다. "abc"면 \0까지 포함해서 4byte인데 이걸 유니코드에서

컴파일하면 여전히 4바이트이다. 그래서 유니코드 상수로 하여 L"abc"로 하면 8바이트가 된다. 그러나 이렇게 하면 지금 당장 컴파일이 안되므로 역시 매크로를 만들어 왔다.

- _T, TEXT : _T("abc") 이렇게 쓰면 컴파일될 때 현재 상황은 "abc"가 되고 유니코드로 컴파일하면 L"abc"가 된다.

TEXT는 API용이고 _T는 MFC용이다.

3. 함수사용

- strcpy는 char*를 인자로 받는다. 그래서 유니코드에서는 이 함수를 쓰지 못한다.

그래서 유니코드용 문자열 복사 함수를 만들어 놓았다. wcscpy(short int* )

그런데 지금 코딩할 때는 이걸 쓸 수 없으므로 역시 매크로를 만들어 놓았다. : _tcscpy

이 함수는 지금 컴파일 하면 strcpy가 되고 나중에는 wcscpy가 된다.

strcat, strlen등도 마찬가지이다. 즉, _tcslen, _tcscpy 이렇게 _tcs만 앞에 붙인다.

그런데 atoi함수같은 경우는 _ttoi, sprintf는 _stprintf이다.

즉 간혹 두 번 째에 t가 나올 경우가 있다.

- MSDN찾는 방법

strcpy : 위는 ansi, 두번째는 유니코드용, 밑에 TCHAR Routine에 _tcscpy가 나온다.

- API에 CreateWindow가 있다면 CreateWindowA는 ANSI용이고 CreateWindowW는 유니코드용이다. 이렇게 두개 함수가 있으므로 그냥 사용하면 된다.

- PTSTR과 LPTSTR은 같은 의미이다. 윈3.1때는 포인터에 NearPointer 2바이트가 있었고, 4바이트짜리 포인터가 있었다. 그래서 long형이 아닌 걸 만들어 놓았다.

지금은 세그먼트가 없으므로 LPCTSTR이나 PCTSTR차이가 없다. 그래서 PTSTR은 사용하지 않는다.

- char temp sz[100];

for(i = 0; i

이렇게 하면 틀린다. 왜냐하면 유니코드가 아니면 100이므로 괜찮지만 유니코드에서는 short int로 바뀌므로 200이 된다. 그래서 sizeof(sz)/sizeof(TCHAR)로 해줘야 한다.


♣ 윈도우 문자열 함수


- CompareString : 문자열 비교하는 api함수이다. c 런타임함수로 strcmp함수가 있으니까 이걸 쓰거나 _tcscmp를 쓰면 되는데 이 함수는 문법적으로는 유니코드를 지원하지만 논리적으로는 지원하지 않는다.

유니코드는 한글, 알파벳이 한꺼번에 모여있다. 그래서 같은 국가문자들끼리만 비교해주려면 CompareString함수를 써야한다. CompareString함수의 첫 번째 인자가 지역ID를 나타낸다. 즉, 이 인자를 사용해서 문자의 EMt을 검사함으로서 두 문자열을 비교하게 된다. 이런 동작은 단순히 숫자를 비교하는 C런타임함수보다 훨씬 의미가 더 있다. (C런타임함수 strcmp, wcscmp등은 문자열에서 코드 포인트의 값을 비교한다. 즉, 함수는 실제 문자의 의미를 무시하고 단순히 각 문자의 숫자 값을 검사한다.)

- 즉 문자열 대소비교할 때 같은 버퍼 안에 한글, 영문이 섞여있을 때는 이 API함수를 써야한다.

- CharLower, CharUpper함수들은 ansi가 없고 유니코드 전용함수들이다.

- 이런 함수들을 쓸때는 다음과 같이 코딩한다.

#ifdef _UNICODE

CharLower();

#else

tolower();

#endif

- IsTextUnicode : 텍스트가 ANSI인지 유니코드인지 결정하는 함수로서 참, 거짓을 반환한다. 즉, 버퍼가 유니코드인지 ANSI인지 판단해주는 함수이다.

PDA는 윈도우CE를 쓴다. 메모장에서 작성한걸 pda에서 쓰려면 먼저 유니코드로 변환해야 하는데 이럴 때 이 함수를 써서 유니코드인지 아닌지를 먼저 판단한다.

- DWORD IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);

- 함수인자로는 첫 번째 인자는 비교하고자 하는 버퍼주소인데 이때 버퍼문자열이 유니코드 문자열인지 ANSI 문자열인지 알지 못하므로 void포인터형이다.

두 번째 인자는 버퍼 바이트 수인데 역시 버퍼내용을 모르기 때문에 문자 카운트가 아닌 바이트의 카운트가 된다. 세 번째 인자는 비교하는 방법(옵션인데 null을 준다)으로 되어있다.

특히 이 함수는 통계적으로 판단한다. 즉 버퍼에 유니코드가 더 많으면 유니코드라고 판단해준다.

♧ 유니코드와 ANSI간의 문자열 변환

- MultiByteToWideChar : ANSI를 유니코드로 변환

- WideCharToMultiByte : 유니코드를 ANSI로 변환

- com은 os와 상관없이 반드시 유니코드를 써야한다.

- .Net : 실행가능한 개체를 만들자는게 목표이다. 실행가능한 개체란 소스상태가 아니고

컴파일된 상태를 말한다. 그래서 com도 같은 목표를 가지고 있다.

출처 : http://tomeii.com/bbs/board.php?bo_table=tipntech&wr_id=119&page=6

by 꿈꾸는데브맨 | 2010/11/03 23:16 | VC++ | 트랙백 | 덧글(0)

유니코드에 대비한 프로그램을 작성하는 여섯가지 원칙

유니코드에 대비한 프로그램을 작성하는 여섯가지 원칙

MBCS는 한 문자를 표현하는데 여러 바이트를 사용하는 것을 말한다. 일반적인 영문자의 경우 모두 한 바이트로 표시되지만, 한글과 같은 경우에는 두 바이트를 사용한다. 또한 두 바이트를 사용하더라도 인코딩 규칙에 따라서 서로 다른 두 바이트가 생성된다. 따라서 인코딩 규칙이 맞지 않는 경우에는 제대로 된 문서를 읽을 수 없는 불편함이 있다. 이러한 불편함을 해결하기 위해서 나온 것이 유니코드다. 유니코드에 대해선 이미 많은 문서에서 소개가 되었기 때문에 별도로 설명하진 않겠다. 혹시 좀 더 자세한 내용이 궁금하다면 http://www.jinsuk.pe.kr/Unicode/Unicode_intro-kr.html를 방문해 보도록 하자.

Windows NT에 기반한 운영체제의 경우 커널 코드가 유니코드를 통해서 작성 되었다. 문자열을 입력 받는 API의 경우 유니코드 버전이 기본적으로 사용된다. 만약 MBCS 버전의 API를 호출한다면 내부적으로 MBCS문자열을 유니코드로 변경한 후에 다시 유니코드 버전의 API를 호출하게 된다. 따라서 MBCS 버전의 프로그램을 작성하는 것은 NT 기반의 운영체제에서는 비효율 적이다. 이러한 점 때문에 최근에는 대부분의 업체에서 NT 기반의 프로그램은 유니코드 버전을 출시하고 있다. 유니코드와 MBCS 빌드에 상관없이 유연하게 컴파일 되는 프로그램을 만들기 위해서 지켜야할 여섯 가지 기본 원칙에 대해서 알아보자.

첫째, 문자열 타입은 T형을 쓴다. T형의 경우 유니코드, MBCS 빌드에 상관없이 적절한 타입으로 변환되기 때문에 빌드가 변경된다고 해서 따로 타입을 수정해 주는 불편함이 없다. char를 사용할 장소에 TCHAR를, char *를 사용해야 한다면 LPTSTR을, const char *을 사용해야 한다면 LPCTSTR을 사용하도록 한다.

둘째, 문자열 리터럴은 항상 TEXT 매크로로 묶어 둔다. 문자열 리터럴은 프로그램 내에서 사용되는 문자열 상수를 의미한다. 그런데 이러한 문자열 상수의 경우 유니코드 빌드에선 앞에 L을 붙여서 wchar_t형이 되어야 한다. 즉, 보통의 경우엔 "%s\n"과 같이 사용하면 되지만, 유니코드 빌드에선 L"%s\n"로 변경해 주어야 한다. 이러한 작업을 일일이 빌드가 바뀔 때 마다 해주는 것은 매우 번거롭고 오류가 많이 나는 일이다. 이러한 작업을 도와주는 것이 TEXT 매크로다. 위에 언급된 문자열 상수의 경우에도 TEXT("%s\n")과 같이 사용하면 MBCS 빌드에선 "%s\n"이, 유니코드 빌드에선 L"%s\n"이 된다. 매크로가 알아서 처리해 준다. 따라서 문자열 리터럴은 항상 TEXT 매크로로 묶어주도록 하자.

셋째, CRT 문자열 함수는 T타입 함수를 사용한다. T형과 마찬가지로 이러한 함수들은 빌드에 따라 적절한 인자를 입력으로 받는다. 예를 들자면 문자열을 복사하는 strcpy에 대응하는 함수로는 _tcscpy가 있다. _tcscpy는 유니코드 빌드에선 인자를 wchar_t로 받고, MBCS빌드에선 인자를 char로 받는다. 따라서 _tcscpy를 사용하고 인자를 T형을 사용한다면 빌드가 변경된다고 해서 직접 수정해야 하는 부분이 없다. 아래 표에는 일반적으로 자주 사용하는 문자열 함수들과 거기에 대한 T타입 함수를 표시해 두었다. 표를 살펴보면 알겠지만 변환 규칙은 무척 간단하다. str로 시작하는 함수는 _tcs로 치환 하면 되고, 그렇지 않은 함수들은 앞에 _t를 붙이면 된다. 물론 그렇지 않은 함수들도 일부 있다. 그러한 함수들은 MSDN을 이용하면 손쉽게 T타입 함수명을 알 수 있다.

일반 함수명T타입 함수명기능
strcpy_tcscpy문자열 복사
strncpy_tcsncpy특정 길이 문자열 복사
strcat_tcscat문자열 추가
strstr_tcsstr문자열 검색
strchr_tcschr문자 검색
strrchr_tcsrchr역순 문자 검색
strcmp_tcscmp문자열 비교
stricmp_tcsicmp대소문자 구분 없이 문자열 비교
mkdir_tmkdir디렉터리 생성
fopen_tfopen파일 열기

넷째, 길이와 크기를 구분한다. 문자열에는 길이와 크기가 있다. MBCS 빌드에서 기본적인 문자 단위로 사용되는 char형의 경우 그 크기가 1바이트 이기 때문에 크기와 길이가 동등한 의미를 가진다. 이러한 이유로 기존의 MBCS 빌드에서 사용하던 많은 코드가 크기와 길이를 정확하게 구분하지 않고 혼용해서 사용하고 있다. 하지만 유니코드 환경으로 넘어오면 크기와 길이는 항상 달라진다. 따라서 함수의 인자가 길이와 크기 중 어떠한 것을 요구하는지 판단해서 정확하게 사용하도록 해야 한다.

다섯째, std::string을 사용하는 경우다. std::string의 경우 ANSI 문자열을 표현하도록 선언된 클래스다. 유니코드 문자열을 표현하는데 사용할 수 있는 타입으로 std::wstring이 있다. 이 둘을 빌드 타입이 변경될 때 마다 바꿔줘야 하는 것은 번거로운 일이다. 이쯤되면 std::tstring이 없는지 궁금해 질 것이다. 하지만 std::tstring은 없다. 없으면 우리가 만들어야 한다. std::string의 경우 std::basic_string<char>로 선언된 것이고, std::wstring의 경우 std::basic_string<wchar_t>로 선언된 것이다. 따라서 우리는 아래와 같이 std::tstring을 정의할 수 있다.

1namespace std { typedef basic_string<TCHAR> tstring; }  
tstring; } " originalCode="namespace std { typedef basic_string tstring; } ">view plain | print | copy to clipboard | ?

namespace std { typedef basic_string<TCHAR> tstring; }

마지막으로 일부 함수나 메시지 인자의 경우 반드시 char나, wchar_t로 취급해야 하는 경우가 있다. 이러한 경우 부득이하게 빌드에 따라서 문자열을 변환해서 사용해야 하며 빌드가 변경되면 반드시 코드를 수정해야 한다. 따라서 처음 작성시에 안전하게 두 가지 빌드로된 버전을 모두 작성해 놓거나 아니면 다른 빌드에서 컴파일 할 경우 에러가 나도록 처리해 두면 편리하다. 아래와 같은 전처리기를 사용하면 쉽게 작성할 수 있다. 유니코드 빌드에선 _UNICODE가 선언된다는 점을 기억해 두자.

1#ifdef _UNICODE  
2// 유니코드 빌드에서 수행할 내용  
3#else  
4// MBCS 빌드에서 수행할 내용  
5#endif  
view plain | print | copy to clipboard | ?

#ifdef _UNICODE // 유니코드 빌드에서 수행할 내용 #else // MBCS 빌드에서 수행할 내용 #endif

만약 현재 프로그램이 MBCS 기반이고 유니코드 부분을 지금은 신경 쓰지 않아도 된다면 #error 전처리기를 사용하면 된다. 이렇게 하면 유니코드로 빌드 할 경우 컴파일 오류가 발생하기 때문에 어떤 부분이 수정되어야 하는지 바로 찾을 수 있기 때문에 편리하다.

1#ifdef _UNICODE  
2// 유니코드 부분은 작성 필요  
3#error 이 프로그램은 유니코드 빌드로 컴파일되지 않습니다.  
4#else  
5// MBCS 빌드에서 수행할 내용  
6#endif  

 

by 꿈꾸는데브맨 | 2010/11/03 23:08 | VC++ | 트랙백 | 덧글(0)

C, C++ Unicode

C, C++ Unicode

(1) Unicode text 문자열

Windows 98 API 부분적으로 유니코드 문자열을 지원하였다. Windows 2000 NT API 유니코드와 ANSI 문자열을 지원한다. 그러나 Windows CE Unicode 지원한다.

MBCS : Multi-Byte Character String. 특수문자 다음에 나오는 문자는 서로 다른 문자체계의 문자임을 알려 주는 구분자로 사용.

Unicode : Wide byte character 방식. ANSI 문자의 경우 상위 바이트는 NULL 되며, 압축 알고리즘에서는 반복적으로 발생되는 NULL 최적화한다.

 

(2) 일반 문자열과 문자 데이터

유니코드 데이터 형인 wchar_t 사용할 수도 있으나, tchar.h include 시키고, TCHAR 데이터형을 사용하여 definition 따라 char wchar_t형으로 적절히 변환할 있다.

 

#define _UNICODE // TCHAR wchar_t 형으로 대치

#define _MBCS  // TCHAR char 형으로 대치

 

문자열 포인터는 LPSTR 데이터형 대신 LPTSTR 데이터형을 사용하여 definition 따라 char * wchar_t * 형으로 적절히 변환할 있다.

 

(3) 상수문자열

LPTSTR lpszStr = "My string";           // 문자열을 ANSI 문자열로 간주

                                                     // 데이터형 불일치로 에러 발생

LPTSTR lpszStr = _T("My string");     // _UNICODE 정의되어 있으면 _T() 유니코드

                                                     // 문자열 상수로 변환하고, _MBCS 정의되어 있으면

                                                     // ANSI 문자열 상수로 변환한다.

LPTSTR lpszStr = TEXT("My string"); // 상동

LPWSTR lpszStr = L("My string");      // 유니코트 문자열로 지정하는 매크로 함수 L()

 

(4) 문자열 버퍼 길이 계산

#define _UNICODE

TCHAR szBuffer[200];                               // szBuffer 크기는 400 bytes

DWORD dwlen;

dwlen = sizeof(szBuffer);                           // 400 bytes

dwlen = sizeof(szBuffer) / sizeof(TCHAR);  // 실제 저장 가능한 유니코드 문자 개수는 200

 

(5) 표준 문자열 라이브러리 함수

표준 C 런타임 함수 strlen() 해당하는 유니코드 함수는 wcslen()이지만, _tcslen() 사용하면 definition 정의에 따라 컴파일시에 적절히 변환된다.

 

             기능                                ANSI 함수    유니코드 함수   일반 문자열 함수

================================ ============ ============= ==================

문자열의 길이를 반환하는 함수          strlen()        wcslen()         _tcslen()

문자열을 접합하는 함수                strcat()        wcscat()         _tcscat()

문자열에서 문자를 찾는 함수             strchr()        wcschr()        _tcschr()

문자열을 비교하는 함수                strcmp()       wcscmp()       _tcscmp()

문자열을 복사하는 함수                    strcpy()        wcscpy()        _tcscpy()

부분 문자열을 찾는 함수                   strstr()         wcsstr()         _tcsstr()

문자열을 역순으로 저장하는 함수       strrev()        _wcsrev()       _tcsrev()

================================ ============ ============= ==================

 

(6) ANSI 문자열과 Unicode 문자열 간의 변환

mbstowcs(WCHAR *des, char *src, int BufferSize)  :

Multi-Byte String Wide Character  String(유니코드)으로 변환.

wcstombs(char *des, WCHAR *src, int BufferSize)  :

Wide Character String(유니코드) Multi-Byte String으로 변환.


(7)
ANSI 문자열과 Unicode 문자열 출력 함수
ANSI :      printf           sprintf              scanf
Unicode:  wprintf        swprintf           wscanf
TCHAR :   tprintf          stprintf              tscanf


출처 :
http://ryongs.egloos.com/253633

by 꿈꾸는데브맨 | 2010/11/03 23:03 | VC++ | 트랙백 | 덧글(0)

생활지수(식중독지수+불쾌지수+먼지농도)


- 주요사용 부품
: Atmega16, 먼지센서, 온도센서(SHT1X)

- 기 능
: 온습도, 먼지농도를 Zigbee로 전송
-  온습도 정보와 먼지농도를 가지고
   생활지수 계산 및 정보표시

- 윈도우 APP : MFC(VC2010)

EnerBio.exe

by 꿈꾸는데브맨 | 2010/08/05 19:57 | AVR ATmega | 트랙백 | 덧글(0)

DAC Converter Module (EB-250)

Serial To Analog Convertor Module Manual







● 개 요
디지털 데이터를 아날로그 출력(0~2.5V)으로 변환시키는 모듈로서 마이크로프로세서(ATmega8)에 변환 프로그램이 내장되어 있으며 타 기기와 연동이 쉽도록 RS-232방식의 인터페이스를 사용합니다.


● 사 양
  -12-Bit Resolution
  -5V Operation
  -Input Data : 3Wire Cascadable Serial Interface
  -Output Voltage : 0~2.5V


● 적용분야
  -Digital Calibration
  -Industrial Process Control
  -Automatic Test Equiment
  -Sensor Network


소비자가 : 60,000 원
문의 : 에너바이오텍 (TEL:031-908-4616)

DATASHEET
  Serial_To_Analog_Convertor_Module_Manual.pdf (한글)
  Serial_To_Analog_Convertor_Module_Manual(English).pdf (영문)

by 꿈꾸는데브맨 | 2010/06/30 13:50 | AVR ATmega | 트랙백 | 덧글(0)

먼지센서(NIDS)

먼지센서(NIDS)



위에 대신전자의 먼지센서의 단자는 4개입니다.

위에 보시는 그림에서 오른쪽 부터 1번 ~ 4번 핀입니다

1 pin : GND
2 pin : P2 (출력2)
3 pin : VCC (DC 5V)
4 pin : P1 (출력1)

입니다.
센서의 성능은 괜찮은것 같습니다. 공기청정기등에 쓰이는 방식이라고 합니다.
하지만 전원이 인가되고 안정적인 출력을 얻기 위해서 1분정도 걸리는것 같습니다.

MCU와 연결 회로도는 아래와 같습니다.
출력 포트 P1은 MCU의 인터럽트 핀으로 각각 연결됩니다.
두개의 인터럽트 핀으로 연결되는 이유는 Falling / Rising Edge를 모두 검출하기 위해서입니다.

Atmega8 과 연결 회로도
NIDS 먼지센서는
아래 그림과 같이 폴링에지의 시간비율로 연기 또는 먼지의 농도를 확인합니다.
데이터 쉬트에는 30초가 적당하다고 되어 있더군요
즉, 30초중 폴링 에지가 된 시간만큼의 비율을 농도로 계산합니다.

폴링에지되었을때 타이머를 카운트하여

COUNT / 30000 (ms) * 100 = 비율(%)

따라서 1ms 의 타이머가 동작되어야 합니다.



소스 (Atmega8 기준)



unsigned long m_lTimer=0;
unsigned long g_clkStart=0;
unsigned long g_clkDelay=0;

unsigned int nAver = 0;


//1. 우선 타이머 레지스터 동작
void init_TIMER(void) {
     // Timer Counter 2
     // 16MHz, 1ms , OVF Interrupt
 
     TCCR2 = (1<<CS02)|(0<<CS01)|(0<<CS00);
     TCNT0 = 256-250;
     TIMSK  =  (1<<TOIE2);  // Overflow Interrupt Enable
 }

// 오버플로우 인터럽트 발생
ISR(TIMER2_OVF_vect) {
     g_clkDelay++;    // 1ms마다 증가
}

unsigned long TIMER_GetCount(void) {
    return g_clkDelay;

}

//2. 외부 인터럽트 동작
ISR(INT0_vect)      // Any Change 인터럽트 설정 : 변화가 있으면 모두 처리
{
    // Rising edge (END)
    if(PIND & 0x04)
    {
        // 상승 에지
        // 카운터 증가 멈춤
    }
    else
    {
        // 하강 에지
        // 타이머에 의해 카운터 증가
    }

}

unsigned int m_nDustTimer[12] = {0,};


//3. 먼지 농도 계산

void GetNIDS(void)
{
    unsigned long ltemp  =  0;
    unsigned int nSum = 0;
    unsigned char ctemp = 0;

     ltemp = TIMER_GetCount();        //현재 카운터 저장
 
    if(ltemp <  (g_clkStart+2500));     //2.5초 마다 샘플링 (2.5 * 12 = 30 sec)
    else
    {
          m_nDustTimer[m_cCnt++] = m_lTimer;
          g_clkStart = TIMER_GetCount();
          m_lTimer = 0;
          if(m_cCnt >= 12)
              m_cCnt = 0; 
          for(;ctemp<12;ctemp++)
         {
             nSum += m_nDustTimer[ctemp];
         }

        nAver = nSum / 300;

        printf("[AV[%d ms] : %d %%]\r\n", nSum, nAver);

 }

DUST_PS02C-PWM.pdf

by 꿈꾸는데브맨 | 2010/06/24 10:14 | AVR ATmega | 트랙백 | 핑백(3) | 덧글(0)

식중독 지수 표시 전광판

Zigbee무선모뎀을 이용하여 무선으로 온습도를 수신하고
이를 Segment에 표시함

by 꿈꾸는데브맨 | 2010/05/04 09:39 | AVR ATmega | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶