C언어는 날짜/시간을 구할 때 하나의 함수로만 되는 것이 아니라, 다음과 같이 약간 복잡합니다.

time() 함수로, 현재 경과된 초(sec), 즉 "유닉스 시간"을 구한 후, 그것을 localtime() 함수로 연월일 시분초로 분리하여 구조체에 저장합니다.

C에서, 오늘 시각/날짜 (현재 날짜, 시간) 출력 예제


파일명: 0.cpp
#include <stdio.h>
#include <time.h>


void main(void) {
  time_t timer;
  struct tm *t;

  timer = time(NULL); // 현재 시각을 초 단위로 얻기

  t = localtime(&timer); // 초 단위의 시간을 분리하여 구조체에 넣기


  printf("유닉스 타임 (Unix Time): %d 초\n\n", timer); // 1970년 1월 1일 0시 0분 0초부터 시작하여 현재까지의 초

  printf("현재 년: %d\n",   t->tm_year + 1900);
  printf("현재 월: %d\n",   t->tm_mon + 1);
  printf("현재 일: %d\n\n", t->tm_mday);

  printf("현재 시: %d\n",   t->tm_hour);
  printf("현재 분: %d\n",   t->tm_min);
  printf("현재 초: %d\n\n", t->tm_sec);

  printf("현재 요일: %d\n", t->tm_wday); // 일요일=0, 월요일=1, 화요일=2, 수요일=3, 목요일=4, 금요일=5, 토요일=6
  printf("올해 몇 번째 날: %d\n", t->tm_yday); // 1월 1일은 0, 1월 2일은 1
  printf("서머타임 적용 여부: %d\n", t->tm_isdst); // 0 이면 서머타임 없음

}



실행 결과 화면:
D:\Z>cl 0.cpp && 0.exe
0.cpp
유닉스 타임 (Unix Time): 1160032094 초

현재 년: 2006
현재 월: 10
현재 일: 5

현재 시: 16
현재 분: 8
현재 초: 14

현재 요일: 4
올해 몇 번째 날: 277
서머타임 적용 여부: 0
D:\Z>



time.h 에 시간 구조체가 다음과 같이 정의되어 있습니다.

struct tm {
  int tm_sec;   /* Seconds */
  int tm_min;   /* Minutes */
  int tm_hour;  /* Hour (0--23) */
  int tm_mday;  /* Day of month (1--31) */
  int tm_mon;   /* Month (0--11) */
  int tm_year;  /* Year (calendar year minus 1900) */
  int tm_wday;  /* Weekday (0--6; Sunday = 0) */
  int tm_yday;  /* Day of year (0--365) */
  int tm_isdst; /* 0 if daylight savings time is not in effect) */

};




업데이트: 비주얼C 2005 이상에 최적화: ▶▶ C언어] localtime_s 함수 사용법: 비주얼 Visual C 2005 이상에서

출처 : http://mwultong.blogspot.com/2006/10/c-current-date-time.html

'C/C++언어' 카테고리의 다른 글

이클립스로 SFTP 사용하기  (0) 2008.06.24
C에서 string 문자열을 float 로 바꾸기  (1) 2008.06.15
LEX & YACC  (0) 2008.06.07
Lex와 Yacc의 사용법 강좌  (0) 2008.06.07
고정 소수점 (C++언어 버젼)  (0) 2008.05.09
출처 삶 그리고 깨달음 | 프리맨
원문 http://blog.naver.com/lonekid/60008258279

알다시피 실수를 표현하는 방법에는 부동소수점과 고정소수점 두 가지가 있다.

부동소수점은 일반적으로 C에서 float 이나 double 형으로 표현되는 방식이다. 이에 비해 고정소수점은 정수부와 소수부에 고정 비트수를 할당하여 [n.0 ~ n+1.0) 의 범위를 표현하는 방식이다. 즉 지수승은 표현하지 못하며 소수부에 대해 [0 ~ 1) 의 범위를 표현하는 방식이다. 이런 연유로 인해 고정소수점은 일반적으로 정수와 동일한 비트 표현을 갖기 때문에 정수연산과 동일한 레벨에서 처리할 수 있다.


아무리 FPU가 탑재되어 있다하더라도 정수 연산에 비해 부동소수점 연산은 수십배 이상 느리다. 그렇기 때문에 지수승에 의한 넓은 범위의 수치를 다루는 경우가 아니라면 고정소수점을 사용하는 것이 충분한 가치를 갖는다. 일반적으로 학문적 수준에서의 알고리즘들은 실수 구간의 연속 데이타를 대상으로 하지만 컴퓨터는 기본적으로 양자화된 이산(정수) 데이타를 대상으로 한다. 즉, 컴퓨터에 있어 알고리즘의 최종 결과는 대부분 정수이다. 그렇기 때문에서 알고리즘을 컴퓨터로 구현함에 있어 실수가 아닌 정수를 대상으로 하는 고속화된 이산(정수) 알고리즘들이 고안되는 것이다.


일반적으로 실수 알고리즘들은 [0 ~ 1) 범위의 노말라이즈된 수치로 표현되는 것이 보통이다.

정수부와 소수부에 각각 16비트씩 할당하는 16:16 고정소수점을 생각해보자. 정수부는 -32768 ~ +32767의 범위를 표현할 수 있으며 소수부는 [0 ~ 1) 의 범위를 65536 단계의 해상도(소수점 이하 4~5자리의 정확도)로 표현하게 된다. 즉, 0.1은 6554(65536*0.1), 0.5는 32768(65536*0.5), 0.8은 52429(65536*0.8)로 표현된다. 이렇게 표현되는 고정소수점에 대한 가감승제 연산은 컴퓨터 입장에서 32비트 정수에 대한 가감승제 연산과 동일하다. 다만 16비트 소수부에 대한 자리수만 고려해 주면 된다.


이렇게 표현되는 고정소수점에 대한 수학 클래스를 예시한다.

이 클래스에서는 고정소수점 버전의 삼각함수(Sin, Cos, Tan)를 테이블 방식으로 구현하고 있는데 이해하는데 어려움은 없을 것이다.


김인대



// 16:16 fixed point constant

#define FIXED_PI2       102944      // (3.1415926535 / 2) * 65536

#define FIXED_2PI       411775      // (2 * 3.1415926535) * 65536

#define FIXED_PI        205887      // 3.1415926535 * 65536

#define FIXED_R2D       3754936     // (180 / 3.1415926535) * 65536

#define FIXED_D2R       1144        // (3.1415926535 / 180) * 65536

#define FX_R2D(fxR)     ::MulDiv((fxR), 180 * 65536, FIXED_PI)

#define FX_D2R(fxD)     ::MulDiv((fxD), FIXED_PI, 180 * 65536)

 

#ifndef _countof

#define _countof(a)     (sizeof(a)/sizeof(a[0]))

#endif

 

// 16:16 fixed point

typedef long CFixed;

 

// 16:16 fixed point math class.

class CFxMath

{

public:

    static int ToInt(CFixed fxDeg)      { return fxDeg >> 16; }

    static int Round(CFixed fxDeg)      { return (fxDeg + 32768) >> 16; }

    static double ToDbl(CFixed fxDeg)   { return fxDeg / 65536.0; }

    static CFixed ToFx(int n)           { return n << 16; }

    static CFixed ToFx(double d)        { return CFixed(d * 65536); }

   

    static CFixed FxSin(CFixed fxDeg);

    static CFixed FxCos(CFixed fxDeg)   { return FxSin(fxDeg + 90 * 65536); }   // sin(deg + pi/2)

    static CFixed FxTan(CFixed fxDeg);

 

private:

    enum

    {

        eSinTableResolution = 7     // The resolution(bits) of fraction part.

    };

    static USHORT m_awSinTable[90 * (1 << eSinTableResolution)];    // 0 ~ 89.n degree

    static bool m_bInitSinTable;

    static bool InitSinTable();

};

 

// static

CFixed CFxMath::FxSin(CFixed fxDeg)

{

    // Normalize to -360 ~ +360 degree.

    if (fxDeg <= -360 * 65536 || 360 * 65536 <= fxDeg)

    {

        fxDeg = fxDeg % (360 * 65536);

    }

   

    // Normalize to 0 ~ 360 degree.

    if (fxDeg < 0)

    {

        fxDeg = (360 * 65536) + fxDeg;  // sin(2*pi + n) == sin(n)

    }

   

    // Adjust angle for quadrant.

    int nQuad = fxDeg / (90 * 65536);

    switch (nQuad)

    {

    case 1:     // 90 ~ 180 degree

        fxDeg = (180 * 65536) - fxDeg;

        break;

    case 2:     // 180 ~ 270 degree

        fxDeg = fxDeg - (180 * 65536);  // -sin(fxDeg)

        break;

    case 3:     // 270 ~ 360 degree

        fxDeg = (360 * 65536) - fxDeg;  // -sin(fxDeg)

        break;

    case 0:     // 0 ~ 90 degree

    default:

        fxDeg;

        break;

    }

    ASSERT(0 <= fxDeg && fxDeg <= (90 * 65536));

   

    // Sin table lookup.

    long fxSinValue;

    if (fxDeg == (90 * 65536))

    {

        fxSinValue = 1 * 65536;             // For 90 degree

    }

    else

    {

        int nDegIdx = fxDeg >> (16 - eSinTableResolution);

        fxSinValue = m_awSinTable[nDegIdx]; // For 0 ~ 89.n degree

    }

    return (nQuad < 2) ? fxSinValue : -fxSinValue;  // 16:16 fixed point

}

 

// static

CFixed CFxMath::FxTan(CFixed fxDeg)

{

    CFixed fxCos = FxCos(fxDeg);

    return (fxCos == 0) ? MAXLONG : ::MulDiv(FxSin(fxDeg), 65536, fxCos);

}

 

USHORT CFxMath::m_awSinTable[90 * (1 << eSinTableResolution)];  // 0 ~ 89.n degree

bool CFxMath::m_bInitSinTable = InitSinTable();

 

bool CFxMath::InitSinTable()

{

    const double d2r = 3.1415926535 / 180;

    for (int nDegIdx = 0; nDegIdx < _countof(m_awSinTable); nDegIdx++)

    {

        double dDeg = (double)nDegIdx / (1 << eSinTableResolution);

        double dSin = ::sin(dDeg * d2r);

        m_awSinTable[nDegIdx] = USHORT(dSin * 65536 + 0.5);

    }

    return true;

}

'C/C++언어' 카테고리의 다른 글

고정 소수점 (C++언어 버젼)  (0) 2008.05.09
코드 최적화  (0) 2008.05.09
음 고정소수점 만들기..  (0) 2008.05.09
고정 소수점  (0) 2008.05.09
각 언어별 3중 포인터  (0) 2008.05.06

정녕~ 이럴수가.. 회사에서 printf 를 만들라는 과제를 받아 만들었습니다.

이사님께 튜트리얼 을 좀 배우고 나서 만들어 본 것인데...

정녕 이걸 네이버에 주소값을 검색해보니.. 개털~ 안나오더군요 google 엔 양키들이 한것이 조금 있더군요


한국 사람들이 얼마나 쪼잔한지 알것 같습니다 .ㅋㅋㅋㅋ

하지만 전 과감하게 올립니다!!

구글에 검색했을때 0xB0008000 을 하니 나왔습니다! 바로 검색어가 0xB0008000 이었는데..

ㅡ,ㅡ.. 문제는 VC 에서는 안됩니다.. 그레서 볼랜드 C 에서 햇습니다.

컴파일 옵션에서 메모리 할당을 large 로 바꿔야 돌아갑니다..


자 BC 로 옵션을 마추어 놓고~ 시작을 합니다. 그전에 알아야 할 것들이 0xB0008000 은 바로 텍스트 모드의 메모리 의 첫 주소 입니다.

0xB0008000 은 콘솔창( VC 로 콘솔 모드로 만들면 뜨는 cmd 창 ) 의 잴 왼쪽 위 구석탱이를 가르킵니다. 그 다음은 2바이트씩

0xB0008002 는 2번째를 가르키겠죠. 그곳에 아스키 코드를 넣어주면 출력이 됩니다. 간단하죠?

하지만 왜 2바이트 단위냐~ 바로 첫번째는 글씨( 0xB0008000 ) 이고 두번째는 ( 0xB0008001 ) 은 색입니다.

XRGB 로 4비트로 구성이 되어 있습니다.

X 는밝기

R 빨간

G 초록

B 파란


이런 식 입니다.

그렇다면 맨 왼쪽위에 A 를 출력하고 싶다! 그렇다면


char * p = (char*)0xB0008000;

*p = 0x41;

*(p+1) = 0x04;


자 빨간색 A 가 나옵니다 . 왜 0x04 가 빨간색이냐!?


X R G B

0 0 0 0

검은색입니다.

X R G B

0 1  0 0

빨간색입니다.

비트를 계산하는 방식이

‥‥ 32 16 8 4 2 1

이죠.. 이걸 매치시킨다면!?


X R G B

8 4 2 1

이가 되겠죠. 그렇다면 빨간색은 4, 그럼 파란색은 1, 초록은 2, 하얀색은 모두더한 F 가 되겟죠..참고로 C 언어는 16진수로 인식을 합니다~ 주의하셔야 합니다.


자 그렇다면 가로가 80입니다. 세로는 24이지요. 그럼 다음번째 줄에 A 를 쓰려면

*p+80 을 하면 됩니다. 그럼 다음번째 줄이 되겟죠..

자 아주 간단하지요?

회사 강의 란에 printx 와 putchx 가 있을것 입니다. 제가 만들었죠 훗..


아레는 BC 의 옵션 설정 방법 입니다.

 

사용자 삽입 이미지

사용자 삽입 이미지

그리고 요번엔 예제 실행 파일 입니다.

사용자 삽입 이미지
사용자 삽입 이미지


소스 파일은


#include <conio.h>
 //4 2 1
enum Color{
 C_RED = 0x04,
 C_GREEN = 0x02,
 C_BLUE = 0x01,
 C_BLACK = 0x00,
 C_WHITE = 0x0F,
 C_GRAY = 0x07
 };

void putchxy( int x, int y, char Text, Color eText )
{
 char * pAddr = (char *)0xB0008000;
 pAddr = pAddr + ( ( y * 160 ) + x * 2 );
 *pAddr = Text;
 *(pAddr+1) = eText;
}

void printxy( int x, int y, char * pText, Color eText )
{
 int iOffset = 0;
 while( *pText != 0 )

 {
  putchxy( x + iOffset, y, *pText, eText );
  ++iOffset;
  ++pText;
 }
}

int main()
{
 printxy( 10, 10, "출력하는 예제입니다.", C_RED );
 printxy( 10, 11, "미희야 사랑해", C_WHITE );
 getch();
 return 0;
}


출처 : http://blog.naver.com/312160/150023748818

'C/C++언어' 카테고리의 다른 글

템플릿 사용한 max 만들기  (0) 2008.03.03
<이클립스 디버그 방법>  (0) 2008.01.28
여러 C++ 컴파일러  (0) 2007.09.06
함수포인터란 ?  (0) 2007.09.06
[본문스크랩] 파일 입.출력  (0) 2007.09.06
김영식 교수님
kys@kpu.ac.kr

ODE (Open Dynamics Engine)의 소스를 사용함.
자세한건 www.ode.org 로..

이건 빌드
http://wsl.kpu.ac.kr/%7Ekys/index.html
출처 카페 > 게임 개발자 네트워크 (jz.. / 자존심
원본 http://cafe.naver.com/jzsdn/2284

♧ 유니코드


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

: 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<sizeof(sz); 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도 같은 목표를 가지고 있다.

+ Recent posts