게임 아이템이 붙은 옵션 또는 속성 값을 bool로 사용하면 된다가 보통의 생각이다.

bool을 sizeof로 측정하면 1Byte = 8bit 값이 나오는데 필요한건 1bit를 표현하기 위해 사용하고 있는 값은 1Byte인것이다. 7bit는 낭비로 보이게 마련이다. 이와 같은 경우 선배님들의 해결법은 바로 비트 연산을 이용하는 것이다.


예를 들어 "NPC에게 판매불가, 버리기 불가, 거래 불가" 등등의 속성들 설정할 때 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
typedef unsigned int UINT;
 
// 시프트 연산을 이용하여 해당하는 자리에 비트를 넣어준다.
enum ITEM_ATTRIBUTE
{
    SELL_SHOP    = 1 << 0, // 상점 판매 유무
    THROW_OUT    = 1 << 1, // 버리기 유무
    ITEM_ATTRIBUTE_MAX    = 1 << 32,
};
 
int main()
{
    UINT itemAttr = SELL_SHOP;
    std::cout << static_cast<UINT>(itemAttr & SELL_SHOP) << std::endl;
    std::cout << static_cast<UINT>(itemAttr & THROW_OUT) << std::endl;
 
    UINT itemAttr = SELL_SHOP | THROW_OUT;
    std::cout << static_cast<UINT>(itemAttr & SELL_SHOP) << std::endl;
    std::cout << static_cast<UINT>(itemAttr & THROW_OUT) << std::endl;
    return 0;
}
cs

(itemAttr & SELL_SHOP)으로 확인하면 해당 비트가 1의 상태면 0보다 큰 숫자를 반환하고 

비트가 0의 상태면 0을 반환한다.

원문 링크 : http://msdn.microsoft.com/ko-kr/library/yakksftt.aspx


문자열을 정수로 변환합니다. 이러한 기능의 더 안전한 버전을 사용할 수 있습니다. _itoa_s, _i64toa_s, _ui64toa_s, _itow_s, _i64tow_s, _ui64tow_s를 참조하십시오.

char *_itoa(
   int value,
   char *str,
   int radix 
);
char *_i64toa(
   __int64 value,
   char *str,
   int radix 
);
char * _ui64toa(
   unsigned _int64 value,
   char *str,
   int radix 
);
wchar_t * _itow(
   int value,
   wchar_t *str,
   int radix 
);
wchar_t * _i64tow(
   __int64 value,
   wchar_t *str,
   int radix 
);
wchar_t * _ui64tow(
   unsigned __int64 value,
   wchar_t *str,
   int radix 
);
template <size_t size>
char *_itoa(
   int value,
   char (&str)[size],
   int radix 
); // C++ only
template <size_t size>
char *_i64toa(
   __int64 value,
   char (&str)[size],
   int radix 
); // C++ only
template <size_t size>
char * _ui64toa(
   unsigned _int64 value,
   char (&str)[size],
   int radix 
); // C++ only
template <size_t size>
wchar_t * _itow(
   int value,
   wchar_t (&str)[size],
   int radix 
); // C++ only
template <size_t size>
wchar_t * _i64tow(
   __int64 value,
   wchar_t (&str)[size],
   int radix 
); // C++ only
template <size_t size>
wchar_t * _ui64tow(
   unsigned __int64 value,
   wchar_t (&str)[size],
   int radix 
); // C++ only

value

변환될 수 있는 숫자

str

문자열 결과

radix

다음 value의 기본은; 범위 2–36에 있어야 합니다.

각 함수들은 str에 포인터를 반환합니다. 반환되는 오류가 없습니다.

다음 _itoa_i64toa, 및 _ui64toa 함수는 주어진 value 인수의 자리를 는 null로 끝나는 문자열로 변경하고, str에서 결과( _itoa 에 대한 최대 33, _i64toa 에 대한 65 및 _ui64toa)를 저장합니다. 만일 radix이 10 및 value 가 음수이면 저장된 문자열의 첫 문자는 빼기 기호 ( – )입니다. 다음 _itow_i64tow, 및 _ui64tow 는 각각 _itoa_i64toa, 및 _ui64toa의 와이드 문자 버전입니다.

보안 정보 보안 정보

버퍼 오버런을 방지 하기 위해 , str 버퍼가 변환된 숫자와 후행 null 문자 및 기호 문자를 저장 하기에 충분 한지 확인해야 합니다.

C++에서 이러한 함수는 보다 최신의 보안 대응 함수를 호출하는 템플릿 오버로드를 갖고 있습니다. 자세한 내용은 안전한 템플릿 오버로드을 참조하십시오.

제네릭 텍스트 라우팅 매핑

TCHAR.H 루틴

_UNICODE 및 _MBCS 정의되지 않음

_MBCS 정의됨

_UNICODE 정의됨

_itot

_itoa

_itoa

_itow

_i64tot

_i64toa

_i64toa

_i64tow

_ui64tot

_ui64toa

_ui64toa

_ui64tow

루틴

필수 헤더

_itoa

<stdlib.h>

_i64toa

<stdlib.h>

_ui64toa

<stdlib.h>

_itow

<stdlib.h>

_i64tow

<stdlib.h>

_ui64tow

<stdlib.h>

호환성에 대한 자세한 내용은 소개 단원의 호환성 부분을 참조하십시오.

// crt_itoa.c
// compile with: /W3
// This program makes use of the _itoa functions
// in various examples.

#include <string.h>
#include <stdlib.h>

int main( void )
{
   char buffer[65];
   int r;
   for( r=10; r>=2; --r )
   {
     _itoa( -1, buffer, r ); // C4996
     // Note: _itoa is deprecated; consider using _itoa_s instead
     printf( "base %d: %s (%d chars)\n", r, buffer, strnlen(buffer, _countof(buffer)) );
   }
   printf( "\n" );
   for( r=10; r>=2; --r )
   {
     _i64toa( -1L, buffer, r ); // C4996
     // Note: _i64toa is deprecated; consider using _i64toa_s
     printf( "base %d: %s (%d chars)\n", r, buffer, strnlen(buffer, _countof(buffer)) );
   }
   printf( "\n" );
   for( r=10; r>=2; --r )
   {
     _ui64toa( 0xffffffffffffffffL, buffer, r ); // C4996
     // Note: _ui64toa is deprecated; consider using _ui64toa_s
     printf( "base %d: %s (%d chars)\n", r, buffer, strnlen(buffer, _countof(buffer)) );
   }
}
기본 10:-1 (2 자)
기본 9:12068657453 (11 자)
기본 8:37777777777 (11 자)
기본 7:211301422353 (12 자)
기본 6:1550104015503 (13 자)
기본 5:32244002423140 (14 자)
기본 4:3333333333333333 (16 자)
기본 3:102002022201221111210 (21 자)
기본 2:11111111111111111111111111111111 (32 자)

기본 10:-1 (2 자)
기본 9:145808576354216723756 (21 자)
기본 8:1777777777777777777777 (22 자)
기본 7:45012021522523134134601 (23 자)
기본 6:3520522010102100444244423 (25 자)
기본 5:2214220303114400424121122430 (28 자)
기본 4:33333333333333333333333333333333 (32 자)
기본 3:11112220022122120101211020120210210211220 (41 자)
기본 2:1111111111111111111111111111111111111111111111111111111111111111 (64 자)

기본 10:18446744073709551615 (20 자)
기본 9:145808576354216723756 (21 자)
기본 8:1777777777777777777777 (22 자)
기본 7:45012021522523134134601 (23 자)
기본 6:3520522010102100444244423 (25 자)
기본 5:2214220303114400424121122430 (28 자)
기본 4:33333333333333333333333333333333 (32 자)
기본 3:11112220022122120101211020120210210211220 (41 자)
기본 2:1111111111111111111111111111111111111111111111111111111111111111 (64 자)


클래스 뷰 --> 해당 Dlg (CxxxxxxxDlg) 선택  

--> 속성 창 --> 재정의 클릭 --> PreTranslateMessage 생성


--> 처리 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BOOL CGDStressToolDlg::PreTranslateMessage(MSG* pMsg)
{
    if(pMsg->message == WM_KEYDOWN)
    {
        switch(pMsg->wParam)
        {
        case VK_ESCAPE:
            if(AfxMessageBox(_T("툴을 종료하시겠습니까?"),MB_YESNO) == IDNO)
                return TRUE;
            break;
        case VK_RETURN:
            return TRUE;
        }
        
    }
    // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
 
    return CDialogEx::PreTranslateMessage(pMsg);
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream> 
#include <map> 
#include <vector> 
 
using namespace std; 
 
int main() 
    map<intint>    mapTest; 
    mapTest.insert( pair< int,int >( 1,0 ) ); 
    mapTest.insert( pair< int,int >( 2,0 ) ); 
    mapTest.insert( pair< int,int >( 3,0 ) ); 
    mapTest.insert( pair< int,int >( 4,0 ) ); 
    mapTest.insert( pair< int,int >( 5,0 ) ); 
 
    vector<map<intint>> vmVectorTest; 
    vmVectorTest.push_back(mapTest); 
 
    vector<map<intint>>::iterator vitr; 
    vitr = vmVectorTest.begin(); 
 
    map<intint>::iterator mapitr; 
    mapitr = vitr->begin(); 
 
    do 
    { 
        cout << mapitr->first << " , " << mapitr->second << endl; 
 
        ++mapitr; 
    }while(mapitr != vitr->end()); 
 
    return 0; 
}

vector에 map을 담을 생각을 한 이유는 자유롭게 변형되는 맵 배열을 생각하게 되었다.

현재로써는 사용량이 빈번하지 않을 것으로 예상되지만 유용하게 사용할 일이 있을거란 생각에 테스트 코드를 작성하게 되었다.

 

위의 코드를 보면 vector에 map을 담았지만 다른 각도로 보면 다양한 STL 컨네이너들이 각자 상황에 맞게 포함 될 수 있음을

의미한다. 이 의미는 자유롭게 사용하여 필요할 때 꺼내 사용하면 된다.

 

퍼포먼스를 먼저 생각하는 분이라면 하나의 연산이라도 하지 않아야 한다는 가정이 붙겠지만 일단 요즘 시대의 컴퓨터는

이 정도의 내용을 허용하므로 자유롭게 사용하는게 더 이익일 수있다는 사실을 생각하면 좋다.

 

고정형의 배열을 사용하거나 매번 new를 이용한 배열 생성의 형태라면 vector가 더 효과적이므로 한번 정도 생각을 해볼 수 있는

문장이다.


프로퍼티스 (성질, 특징) 창을 열어 아래 경로의 항목을 True로 변경 시켜준다.

Properties  ->  Appearance  ->  Abolute Align  -> True

 

 변경이 완료되면 Properties 창 하단에 아래와 같이 pos설정할 수 있는 항목이 생긴다.

 

Center -> False 상태에서는 X, Y Position을 설정할 수 있다. True 상태라면 중앙에 위치하게 된다.

0, 0 좌표는 화면 왼쪽 상단의 기본 좌표이다. 좌표를 설정하고 싶다면 픽셀단위 값을 확인 후 입력하면 된다.

 

 

▷ 포인터의 개념 정리

  - 주소를 가르킨다.

  - 메모리는 주소를 가지고 있고 주소를 통해 메모리 접근이 가능하다. 이 주소를 저장하고 있는게 바로 포인터이다.

  - 거대한 데이터(struct와 같은)를 전달 인자(매개 변수)로 전달하는 것은 메모리 낭비이므로 포인터를 전달하면

     거대한 데이터의 위치(주소)만 전달하면 되므로 효과적으로 사용할 수 있다.

 

 ▷ 흔히 책에 있는 예제

    int  nCount = 100;

    int *pCnt;

    pCnt = &nCount;

 

▷ 경험에 의한 예제

   struct stUserBaseInfo{

        int  nUserIdx;

        char[50] nCharName;

        int nCharIdx;

  }; 

   // 위의 이런 구조체가 있다는 가정이라면 거대한 데이터가 된다.

   stUserBaseInfo  meInfo;

   stUserBaseInfo  *pMeInfo;

   pMeInfo = (* stUserBaseInfo) meInfo;

                 ------------------

                     └> "데이터형 변환자"라 부른다.

  // 즉 구조체를 가지는 거대한 데이터나 클래스를 통째로 넘겨 처리가 필요하다면 포인터로 주소만 넘기는

      방법이 보다 효과적이라는 사실이다.

 

▷ 또 다른 예제

   int*  p_info;

  char*  p_chInfo;

  //다른 데이터형일 경우 주소를 가르키려면?

 

  p_chInfo = (char *) p_info;

                 -------

                    └> "데이터형 변환자"를 이용하여 다른 데이터형일 경우 주소를 가르킨다.

 

  p_info가 가르키는 주소  :  p_info

  p_chInfo가 가르키는 주소 : (int *) p_chInfo

 

 

 

▷ 포인터와 const 

  int  gorp = 16;

  int  chips = 12;

 

                      ┌> 다른 변수를 지시할 수 있다. ( p_snack = chips; )

                 ----------

  const  int  *  p_snack = &gorp;

  --------

      └> 지시하는 값은 변경할 수 없다. ( *p_snack = 20; )

 

 

                      ┌> 지시하는 변수는 변경 불가능!!

              -------------

    int  *  const  p_snack = &gorp;

   -----

      └> 값 변경 가능.

 

▷ 더블 포인터

   - 다차원 배열을 접근하는데 사용된다.

   - 책에 나와 있는대로 포인터는 더블 포인터로 받는다라는 부분도 맞겠지만 엄밀히 말하자면 더블 포인터는

     다차원 배열을 접근하는데 유용하게 사용된다는 점이다.

  char*  double_arr[] = {"abc", "def"};

  char** ptr_arr = double_arr;

 

  cout << ptr_arr[0] << endl;

 

출력 결과

abc

 

▷ 다차원 배열을 사용하지 않는 경우

   char*  double_arr[] = {"abc", "def"};

   char*  ptr_arr  =  double_arr[0];

 

   cout << "ptr_arr  :  "  << ptr_arr << endl;

   // 다차원 배열 접근이 아니라면 이렇게 접근이 가능하다.

 

 

'Languages > cplusplus' 카테고리의 다른 글

[STL] Vector + Map 연습 코드  (0) 2013.07.19
[MFC] Dialog Box 위치 변경  (0) 2012.11.26
지수표기 / enum / new 메모리 할당  (0) 2012.10.12
데이터 형변환  (0) 2012.09.26
32bit 자료형 / 64bit 자료형의 크기 정리  (0) 2012.09.26

 

 지수 표기

  +5.37E+16

 

0.000E+N 형식은 소수점을 오른쪽으로 N자리만큼 이동하는 것이고

0.000E-N은 소수점을 왼쪽으로 N자리만큼 이동하는 것이다.

 

 

 → enum

                 ┌>     열거형의 변수 선언할 때 사용됨.  

  enum  spectrum  { red, orange, yellow, green, blue };

                             ------------------------------

                                                  └> 열거자들

 

Ex)  spectrum  band;

       └> spectrum형 열거형 변수는 이미 선언된 값만 대입 가능하다.

             선언 후 값을 대입하지 않으면 Error를 발생한다.

       band = yellow;    // true

       band = 100;        // false   (열거자가 아니므로 실패)

 

→ 열거자가 아닌 값을 대입하고 싶다면?

       band = spectrum(100);

 

 

 → new 메모리 할당

 [typename] * [pointer_name] = new [typename];

 

Ex)  int  *pn = new  int;

                    --------

                         └> int형 데이터를 저장할 새로운 메모리가 필요하다고 프로그램에 알린다.(heap memory)

 

* 컴퓨터의 메모리가 부족하여 new의 메모리 할당 요청을 허용할 수 없는 경우 new는 0값을 리턴한다.

                                                                                                          ----------

                                                                                                        NULL pointer

 

        delete pn;    //메모리 해제 (해제하지 않으면 메모리 누수 발생)

 

* new를 사용하여 메모리를 할당 후 메모리 해제가 필요한 경우 delete를 사용한다.

  메모리 해제가 필요한 경우는 사용할 데이터가 필요가 없는 경우일 뿐이다.

 

 

  정적 바인딩 (static binding)

     사용이 되든 안되는 항상 메모리를 차지하는 방식 (Ex : 배열)

 

 → 동적 바인딩 (dynamic binding)

     new를 사용하면 배열을 실행 시간에 생성할 수 있고 필요 없으면 생성하지 않을 수 있다.

     또는 프로그래미을 실행하는 동안에 배열의 크기를 결정할 수 있다.

 

 int  *psome = new  int[10];        // new를 사용한 동적 배열 생성 예제

 delete[] psome;  //동적 배열 해제.

 

 

char * itoa (int value, char * str, int base);

숫자를 문자열로 형변환이 필요한 경우 사용되는 함수이다.

 

첫번째 전달인자 : 변환할 변수

두번째 전달인자 : 저장할 곳

세번째 전달인자 : 변활할 진수 (2진수, 8진수, 10진수 등등)

 

char buf[10];

int a = 11111;

itoa( a, buf, 10);

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

숫자를 문자열로 변환

int a = 10;

CString str;

str.format ("%02d", a);



Date(날짜)를 문자열로 바꾸어 전송이 필요할 때 (숫자를 문자열로 변환하는 것도 동일하다)

void CRDB::TMDATE(CString *s, time_t tmv)
{
     tm *ptm;
     ptm=localtime(&tmv);
     s->Format("%d-%02d-%02d",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday);
}

void CRDB::TMTIME(CString *s, time_t tmv)

     tm *ptm;
     ptm=localtime(&tmv);
     s->Format("%02d:%02d:%02d",ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
}

 

문제가 되는 코드들에 대해 예제로 정리된 사이트

http://wiki.kldp.org/wiki.php/32bitCodeTo64bit

 

개발할 때 이해를 돕는 사이트

http://blog.naver.com/PostView.nhn?blogId=kkpa1002&logNo=20106022381

http://rusy.tistory.com/entry/32%EB%B9%84%ED%8A%B8-vs-64%EB%B9%84%ED%8A%B8-WIN32-vs-WIN64

 

자료형 

32 bit OS

64bit OS 

 int

 32 bit (4 Byte)

 32 bit

 short

 16 bit

 16 bit

 long

 32 bit

 64 bit

 longlong

 64 bit

 64 bit

 pointer (*)

 32 bit

 64 bit

 long double

 12 bytes

 16 bytes (128 bit)

 size_t , ssize_t

 32 bit

 64 bit

 typedef

 

 

 

#include <stdio.h>
#include <stdlib.h> #include <limits.h>

int main(void)
{

        printf("### 1 Byte = 8 bit ###\n");
        printf("int : %d byte\n",sizeof(int));
        printf("unsigned int : %d byte\n",sizeof(unsigned int));
        printf("long int : %d byte\n",sizeof(long int));
        printf("unsigned long int : %d byte\n",sizeof(unsigned long int));
        printf("long long int : %d byte\n",sizeof(long long int));
        printf("float : %d byte\n",sizeof(float));
        printf("double : %d byte\n",sizeof(double));
        printf("long double : %d byte\n",sizeof(long double));
        printf("(void *) : %d byte\n",sizeof(void *));
        printf("\n");
        printf("INT_MAX = %d\n", INT_MAX);
        printf("UINT_MAX = %ud\n", UINT_MAX);
        printf("LONG_MAX = %ld\n", LONG_MAX);
        printf("ULONG_MAX = %lud\n", ULONG_MAX);

        return 0;

}

아래는 64bit에서의 결과의 예제이다.

### 1 Byte = 8 bit ###
int : 4 byte
unsigned int : 4 byte
long int : 8 byte
unsigned long int : 8 byte
long long int : 8 byte
float : 4 byte
double : 8 byte
long double : 16 byte
(void *) : 8 byte

INT_MAX = 2147483647
UINT_MAX = 4294967295d
LONG_MAX = 9223372036854775807
ULONG_MAX = 18446744073709551615d

몇 가지 유의사항

  • 64bit에서는 포인터의 크기와 int의 크기가 다르다. sizeof(void *) != sizeof(int).
  • 포인터의 크기가 64bit이기 때문에 그 메모리 주소 연산은 32bit의 환경과 다르게 된다.
  • 64bit에서 long 형태의 값을 int 형태로 cast할 때 주의해야 한다. 64bit에서는 sizeof(long)

!= sizeof(int). 그러나 32bit 환경에서는 sizeof(int) == sizeof(long) = 32bit = 4byte.

  • 64bit에서 long 형태의 값을 double으로 cast할 때는 정확도의 손실이 생길 수 있다. significant

figure의 갯수가 long 형태와 double 형태가 다르다는 것을 숙지해야 한다.

  • Fortran에서 integer와 real의 기본 크기는 64bit에서도 여전히 32bit = 4byte이므로, 64bit

integer를 쓰기 위해서는, kind를 이용하거나 아니면 INTEGER*8를 명시해야 한다.

 

  1 #include <iostream>
  2 #include <vector>
  3 #include <time.h>
  4 using namespace std;
  5 
  6 
  7 int main()
  8 {
  9 	// 랜덤 돌릴 범위의 모든 숫자를 저장한다.
 10 	vector<int> LottoNum;
 11 	for (int i = 0; i < 50; ++i)
 12 		LottoNum.push_back((i+1));
 13 
 14 	vector<int> ResultLottoNum;  // 램덤 후 결과값 담을 벡터
 15 	int NumRand = 0;
 16 
 17 	srand((unsigned)time(0));
 18 
 19 	for (int i = 0; i < 25; ++i)
 20 	{
 21 		vector<int>::iterator vcItr;
 22 
 23 		int SelectRandNum = 0;
 24 		SelectRandNum = rand()%LottoNum.size();  //랜덤
 25 
 26 		vcItr = LottoNum.begin() + SelectRandNum; // iterator에 램덤 위치 값 가르키도록 지정.
 27 
 28 		NumRand = *vcItr;   //값을 저장.
 29 		cout << NumRand << " / ";
 30 
 31 		if ((i+1)%5 == 0)
 32 			cout << endl;
 33 		ResultLottoNum.push_back(NumRand);  //최종 결과값 저장 벡터에 데이터 넣기.
 34 
 35 		LottoNum.erase(vcItr);     // 중복되지 않도록 삭제 처리.
 36 	}
 37 	return 0;
 38 }
 39 
 40 


 

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

OnInitDialog() 함수 자동 추가 방법

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

Dialog Box 클래스 추가 후 헤더 파일을 열고 Properties 창에 보면

 

여기에 OnInitDialog 부분이 있는데 추가해주면 자동으로 추가 된다.

 

※ 메뉴에서 View -> Class View를 이용하는 방법도 있으므로 참고.

 

 

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

모든게 귀찮아 수동 추가 하고 싶다면 아래의 내용을 참고

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

Dialog Box를 추가 후 클래스를 생성하게 된다. 그 생성된 헤더파일(.h)에 OnInitDialog() 함수를 생성해준다.

OnInitDialog()함수는 기본적으로 CDialog 클래스에 virtual로 존재한다.

 

1. 헤더파일(.h) 추가 내용

protected:

virtual BOOL OnInitDialog();        //생성한 클래스 헤더파일에 추가한다.

 

2. 씨피피(.cpp) 추가 내용

BOOL    classCreateName::OnDialog()

{

CDialog::OnInitDialog();

 

//TODO : Add extra initialization here

return TRUE;

}

 

모두 완료 되었으므로 초기화 해주고 싶은 내용을  [ //TODO : Add extra initialization here ] 문장 아래에 추가 한다.

대화 상자는 두 가지로 나뉜다.

  -  모달(Modal) 대화 상자

  -  모덜리스(Modeless) 대화상자

 

모달 대화 상자는 메인 흐름을 정지하고 동작하는 대화 상자이며, 모덜리스  대화 상자는 흐름을 방해하지 않고 별개로 작동하는 형태입니다.

 

1. Resource View에서 Insert Dialog를 클릭하면 Dialog Box를 생성할 수 있다.

2. 생성한 Dialog Box에서 오른쪽 버튼으로 Add Class하여 클래스를 추가해 준다.

 

3. 대화 상자를 사용하고 싶다면  클래스 이름으로 생성된 [헤더파일]을 메인 대화상자 .cpp 파일에 코드를 추가 한다.

#include "ModalDlg.h"

 

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

// 모달 대화 상자로 호출 하는 방법 

CModalDlg Dlg;
 INT_PTR nResult = Dlg.DoModal();

 if (nResult == IDOK) 
 {
  AfxMessageBox(_T("Clicked Button OK!"));
 }

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

// 모달리스 대화 상자로 호출 하는 방법

 static CModalDlg Dlg;
 if (Dlg.GetSafeHwnd() == NULL)
 {
  Dlg.Create(IDD_SUBDIG1);
 }

 Dlg.ShowWindow(SW_SHOW);

 

 

 

1. Toolbox - List Control 을 생성한다.

2. Properties - View 를 이용하여 필요한 보기 방식을 지정한다. (보통 : List 방식 사용)

3. 생성된 리스트 컨트롤에서 오른쪽 버튼을 클릭하여 [Add Variable...]을 클릭하여 변수를 만든다.

 

 

4. 데이터를 초기화 및 설정하고 싶다면 OnInitDialog() 함수에 코드를 삽입한다.

m_ctrItemList.InsertItem(0, _T("1 th Test item"));

m_ctrItemList.InsertItem(1, _T("2 th Test item"));

 

5. 컬럼 헤더를 만들어 데이터를 추가하고 싶은 경우 아래와 같이 OnInitDialog() 함수에 코드를 삽입한다.

m_ctrItemList.InsertColumn(0, _T("Count"), LVCFMT_LEFT, 150);

m_ctrItemList.InsertColumn(1, _T("Count"), LVCFMT_LEFT, 150);

m_ctrItemList.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);        //스타일을 지정하지 않으면 출력되지 않는다.

 

 m_ctrItemList.InsertItem(0, _T("1 th Test item"));            //첫번째 컬럼헤더에 값 셋팅
 m_ctrItemList.SetItemText(0, 1, _T("1 th complate"));      //두번째 컬럼헤더에 값 셋팅

  // 컬럼 헤더에 값 추가는 첫번째 컬럼이냐 두번째 컬럼이냐에 따라 다르다... 물론 두번째 컬럼헤더 값 셋팅처럼 첫번째 값 셋팅을 해주어도 무관하다.

 

 

▷ 행 전체 컬럼 선택 할 수 있도록 설정하기

    - BOOL CDialog::OnInitDialog()에 다음과 같이 내용을 추가한다.

     m_ctrCashItem.SetExtendedStyle(LVS_EX_FULLROWSELECT);

이렇게 쉬운걸 한참동안 찾아 헤매었다 ㅡㅡ;;

 

 

visual studio 2005 기준으로 테스트 되었습니다.

 

1.  Dialog Editor에서 Combo Box를 드래그 하여 생성한다.

2.  아래 그림과 같이 화살표 버튼을 누르면 리스트 표시 영역 사이즈를 조정할 수 있다.

     리스트 개수에 맞게 마우스 드래그를 이용하여 늘려 준다.

 

3. 콤보 박스 리스트 추가 및 표현(출력) 방법

    3.1  콤보 박스에 마우스를 올려 놓고 오른쪽 버튼 클릭 [Add VariAble...] 선택!

    3.2  아래와 같은 화면이 나오면 control을 생성한다.

    

 

    3.3 OnInitDialog() 함수에 초기화 하는 내용을 추가한다.

          m_comboServerList.AddString(_T("1 channel"));                   //텍스트 추가
          m_comboServerList.AddString(_T("2 channel"));

          m_comboServerList.SetCurSel(0);                                //텍스트 선택

    3.4 현재 선택된 곳이 어디인지 알고 싶다면 아래와 같이 함수 사용

         index  =  m_comboServerList.GetCurSel();        //현재 선택된 텍스트 값을 int형으로 반환

 

4.  콤보 박스 변경 시 동작 하고 싶을 때...

   - Properties 창에 보면 Control Events 를 클릭하고  동작하고 싶은 내용을 추가한다.

    - 필요한 동작 코드를 안쪽에 삽입하면 내가 원하는 동작을 취한다.

 

5. 콤보 박스 Type 설정

   - Properties 창에 보면 Type이 있다.

 

Dropdown은 Edit가 가능한 상태이다.

Drop List는 선택만 가능한 상태이다.

 

6. 콤보박스 텍스트 가져오기

  CString temp;

   this->m_comboBox.GetLBText(this->m_comboBox.GetCurSel(), temp);

   //GetCurSel()을 호출하면 현재 몇번째 지정하고 있는지에 대한 정보만 넘어온다. 주의가 필요하다.

 

  

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

                              콤보 박스  클래스 함수들 리스트 (펌)

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

▷ CComboBox::AddString - 스트링을 더함.
▷ CComboBox::CComboBox - ComboBox 오브젝트를 생성(구성).
▷ CComboBox::Clear -현재 선택을 지움.
▷ CComboBox::CompareItem - 새로운 리스트 항목의 상태적 위치를 결정.
▷ CComboBox::Copy - 현재 선택을 Copy.
▷ CComboBox::Create - CComboBox를 생성.
▷ CComboBox::Cut - 제거된 텍스트를 복사.
▷ CComboBox::DeleteItem- 항목이 Combo 박스에서 제거.
▷ CComboBox::DeleteString - 스트링을 제거.
▷ CComboBox::Dir - 리스트를 더함.
▷ CComboBox::DrawItem - 양상이 변할 때 불려짐.
▷ CComboBox::FindString - 첫 번째 스트링을 찾음.
▷ CComboBox::FindStringExact - 첫 번째 리스트 박스 스트링을 찾음.
▷ CComboBox::GetCount - 항목의 수를 회복.
▷ CComboBox::GetCurSel - 현재 선택된 항목의 색인을 찾음
▷ CComboBox::GetDroppedControlRect - 스크린 좌표를 되찾음.
▷ CComboBox::GetDroppedState - 리스트 박스가 보일지를 결정.
▷ CComboBox::GetEditSel - 시작과 끝나는 문자의 위치를 얻음.
▷ CComboBox::GetExtendedUI - 디폴트, 확장 사용자 인터페이스의 결정.
▷ CComboBox::GetItemData - 항목과 관련된 비트값을 회복.
▷ CComboBox::GetItemDataPtr - 포인터로서 관련된 비트 값을 회복.
▷ CComboBox::GetItemHeight - 리스트 항목의 높이를 회복.
▷ CComboBox::GetLBText - 리스트 박스로 부터 스트링을 얻음.
▷ CComboBox::GetLBTextLen - 스트링의 길이를 지정.
▷ CComboBox::InsertString - 스트링의 삽입.
▷ CComboBox::LimitText - 텍스트의 길이를 제한.
▷ CComboBox::MeasureItem - Combo 박스 치수를 결정하기 위해 불려짐.
▷ CComboBox::Paste - 현재 커서 위치에서 편집 제어로 삽입.
▷ CComboBox::ResetContent - 모든 항목의 제거.
▷ CComboBox::SelectString - 스트링을 선택, 복사.
▷ CComboBox::SetCurSel - 스트링을 선택.
▷ CComboBox::SetEditSel - 편집 제어에서 문자들을 선택.
▷ CComboBox::SetExtendedUI - 디폴트, 확장 사용자 인터페이스의 선택.
▷ CComboBox::SetItemData - 항목과 관련된 값을 정함.
▷ CComboBox::SetItemDataPtr - 포인터에 대한 관련된 값을 정함.
▷ CComboBox::SetItemHeight - 높이를 지정.
▷ CComboBox::ShowDropDown - 리스트 박스를 보여주거나 숨김.

 

리눅스에 설치된 MySQL 쿼리문을 이용하여 날짜, 시간을 입력하여 정수형으로 변환해주는 함수가 존재한다.

 

select  unix_timestamp('2011-05-30 12:00');

 

이 함수를 이용하면 정수 값  :  1306724400  출력된다.

 

unix_timestamp 값을 날짜, 시간으로 출력하려면 다음과 같이 진행한다.

 

  1 time_t g_itemTime = 1306724400;
  2 struct tm * localtt;
  3
  4 localtt = localtime(&g_itemTime);
  5
  6 cout << localtt->tm_year + 1900 << endl;
  7 cout << localtt->tm_mon + 1 << endl;

 

결과 값을 출력해 봤더니 제대로 나온다... ^^*

 

 

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

▷ 시간 변환시 주의 사항

  struct tm* stTime = localtime(&server.m_time);

  : 포인터로 서버의 시간을 바로 넘기는건 주의가 필요하다.

     왜냐하면 시간의 대한 조작을 하는 경우 시간이 꼬여 잘못된 서버 동작을 일으킬 수 있기 때문이다.

 

비트 연산자는 주로 메모리를 효율적으로 관리하거나 서버와 클라이언트 간의 전송하는 패킷을 효율적으로 주고 받아야 하는 경우 고민해볼 수 있다...

 

C/C++에서 가장 기초인 자료형에 대해 배우게 되는데... 1byte 부터 8byte까지 다양하게 사용이 가능하다...

cout << sizeof(bool); 명령으로 살펴보면 bool 역시 1byte임을 알 수 있다. 게임의 경우 장비에 대한 착용 유무를 확인 한다고 하면 대략 기존 8개 정도(머리, 상의, 하의, 신발, 장갑, 귀걸이 2개 , 목걸이 등등)로 나뉜다...

그렇다면 이 8개를 1byte씩 계산하면 대략 8byte를 사용하지만 4byte int형으로 표현도 가능하다.

우리가 비트의 대한 개념을 배웠다면 숫자 표현이 4byte는 32bit 표현 가능하다.

int형 4byte = 32 bit이므로 비트 표현은 32개 표현 가능..

 

// Bit 단위로 대입
unsigned int  EquipItem = 0;
EquipItem |= 1;
EquipItem |= 4;

// 아이템 존재 유무 확인
for (int i=0; i<32; ++i)
{
	if (EquipItem & (1 << i))
		cout << i << endl;
}


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

만약 bool 자료형을 배열로 만들어 사용한다면이라는 생각을 해보게 되었다..

bool EquipItem[8] = {false, };

cout << sizeof(EquipItem) << endl;

사이즈가 궁금해서 일단 출력해 봤더니 8byte가 나온다...

 

약간의 계산적인 부분이 비트 연산할 때 복잡할거라 생각했지만 이해하고 나니 훨씬 간편하다...

 

어떤 상황이냐에 따라 코드가 달라질 것이다... 기초는 역시 중요한 것 같다...

기초를 튼튼히 하면 할수록 많은 것들이 보인다...

경력 3년이 될 때까지는 계속 머리속에 기초는 외워야겠다는 생각을 해본다...

 

 


visual studio 2005를 사용하던 도중 source safe로 여러명이 작업하는 경우 축적된 변경 코드들이 내 컴퓨터로
유입되면서 선언과 정의 찾아가기가 틀리는 경우가 발생되었다...

visual studio 2005를 종료 후
해당 프로젝트 폴더에 존재하는 0000.ncb 파일을 삭제 후 다시 실행하면 정상적으로 돌아온다...


원리는 다음과 같다... 모든 파일 정보들을 다시 로드하므로 현상 해결이 가능하다...



#ifndef    TEST_H_
#define   TEST_H_

-   내용 생략  -

#endif

> macro wrapper방식을 이용하여 중복 include를 제거하는데 사용되는 예제 코드이다.
   이 코드는 TEST_H_ 가 define 되어 있다면 더 이상 읽지 않는다.

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

#pragma once

  - 내용 생략 -

> 컴파일러에게 이 파일을 한번만 읽으면 되는것을 알려주는 코드이다.

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


두 코드의 차이점은 ifndef은 비교를 지속적으로 하므로 컴파일러 속도가 늦어진다... 하지만 한번 읽으면
더 이상 읽지 않아도 된다는 pragma는 속도가 좀 빠르게 된다... 하지만 두 개의 코드는 동일한 기능을
하고 있다... 컴파일 속도가 조금 더 빠른 방법이 좋지 않을까라는 생각을 해본다...

참고 : #pragma는 표준에서 정의도니 전처리기 지시어가 맞다고 한다.

< #define을 사용하는 경우 >

1. 국가별 코드가 다르게 들어가야 하는 경우.

2. 버전에 따라 코드가 다르게 들어가야 하는 경우.

3. 솔루션(구성 관리자)에 따라 각각 다르게 빌드 되어야 하는 경우. (Ex. Debug, Release, Etc...) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define A_SYSTEM       //기존 코드
#define B_SYSTEM       //신규 추가 코드
 
 
#ifdef A_SYSTEM
      #ifdef B_SYSTEM
              // 신규 추가 코드
      #else
              // 기존 코드
      #endif
#endif
 
==================================================================================
 
#if defined (A_SYSTEM) || defined (B_SYSTEM)
     // 코드 또는 디파인
#endif
 
#if defined (A_SYSTEM) && defined (B_SYSTEM)
     // 코드 또는 디파인
#endif
 
==================================================================================
 
#if defined (A_SYSTEM)
     // 코드 또는 디파인
#elif defined (B_SYSTEM)
     // 코드 또는 디파인
#else
     // 코드 또는 디파인
#endif
 
cs



#define의 장점은 구분이 명확하지만 많이 포함되면 엄청난 난독형 코드가 될 가능성이 높다.

SVN을 이용하여 Revision으로 #define을 대체하는 경우도 존재 한다.


SVN은 Revision 관리가 소홀히 되는 경우 오동작 버그 발생하는 경우를 종종 봐 왔는데 오히려 관리가 소홀하다면 #define이 더 좋을 수 있다는 생각도 든다.


SVN의 시스템 구현별 Revision 관리만 잘 된다면 난독 코드가 될 가능성이 낮기 때문에 개인적으로 선호한다.





1. 자동 형변환이 다르다
   - windows에서 개발 툴로 visual studio를 사용하고 컴파일하면 에러나지 않는 코드는 아래와 같다.

      int a = a * 0.5;

   -  위의 코드를 Linux에서 컴파일하면 오류이다. 자동 형변환이 안된다....-_-;;;

      int a = (int)(a * 0.5);


2. 제공되는 함수가 다르다
   - 윈도우에서 제공하는 함수가 있고 리눅스에서 제공하는 함수가 있으므로 공통으로 사용되는 함수를 사용해야 한다.
   - 윈도우 독자 제공 유요한 함수를 사용하면 리눅스에서는 컴파일 되지 않으므로 멀티 플랫폼으로 개발할 때
     주의가 필요하다.


윈도우 환경에서 개발하고 리눅스 환경에서 구동하는 경우 신입인 나에겐 색다른 경험이기도 하지만 많은 것들을 배울 수 있어 좋다.... 부스트라는 것도 사용해보는데 컴파일할 때는 느리지만 동작에는 최적의 상태를 나타냈기에 사용할거라 예상된다... ^^* 아직 부스트에 대한 부분은 많이 몰라 찾아보고 있다... ^^

http://msdn.microsoft.com/ko-kr/library/dd409393.aspx

visual studio 2010 버전에서 지원하는 내용을 서술했는데... 이해하기 쉽게 접근한 그림이 마음에 든다...

이전에 관심을 갖고 여러 사이트들을 참고하고 봤더니 이해가 쉬워 링크를 걸어 놓았다....
UML을 이용하니 구조 파악하기도 용이하고 내가 무엇을 만들어야 할지도 머리속에 그려지니
용이하게 사용되는것 같다....

+ Recent posts