_countof를 이용하면 정적으로 할당된 배열의 개수를 구 할 수 있다.
예제1>
int n[2];
int rt = _countof(n);
rt에는 2 가 입력된다.
하지만 이것을 포인터로 변환해 버리면 개수를 구 할 수 없다.
예제2>
int* p = n;
int rt2 = _countof(p);
컴파일 오류가 난다.
프로그래밍에 유용하게 쓰기는 힘들꺼 같다.
_countof를 이용하면 정적으로 할당된 배열의 개수를 구 할 수 있다.
예제1>
int n[2];
int rt = _countof(n);
rt에는 2 가 입력된다.
하지만 이것을 포인터로 변환해 버리면 개수를 구 할 수 없다.
예제2>
int* p = n;
int rt2 = _countof(p);
컴파일 오류가 난다.
프로그래밍에 유용하게 쓰기는 힘들꺼 같다.
#pragma once
class CCriticalSection2
{
private:
CRITICAL_SECTION m_cs;
public:
CCriticalSection2()
{
InitializeCriticalSection(&m_cs);
}
~CCriticalSection2()
{
DeleteCriticalSection(&m_cs);
}
inline void Enter() { EnterCriticalSection(&m_cs); }
inline void Leave() { LeaveCriticalSection(&m_cs); }
};
template<class T>
class CMultiThreadSync
{
friend class CThreadSync;
private:
static CCriticalSection2 m_Sync;
public:
class CThreadSync
{
public:
CThreadSync()
{
T::m_Sync.Enter();
}
~CThreadSync()
{
T::m_Sync.Leave();
}
};
};
template<class T>
CCriticalSection2 CMultiThreadSync<T>::m_Sync;
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// 실제사용
//
// class CMyThred : public CMultiThreadSync<CMyThred>
// {
// }
// //구현부분
//
// void CMyThread()
// {
// CThreadSync sync;
// //작업 수행
// }
//
#if !defined (__AutoDetectMemoryLeak_h__)
#define __AutoDetectMemoryLeak_h__
#if defined(_MSC_VER) && defined (_DEBUG)
#define _CRTDBG_MAP_ALLOC // 메모리 누수를 탐지하기 위해 선언 해주어야 한다.
#include <crtdbg.h>
#if !defined (_CONSOLE)
#include <cstdlib> // for Consol Application
#endif
class __AutoDetectMemoryLeak
{
public:
__AutoDetectMemoryLeak ()
{
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF |
_CRTDBG_LEAK_CHECK_DF);
// Consol Application인 경우
#if defined (_CONSOLE)
// Send all reports to STDOUT
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
/* new로 할당된 메모리에 누수가 있을 경우 소스상의
정확한 위치를 덤프해준다.
* ※ _AFXDLL을 사용할때는 자동으로 되지만 CONSOLE
모드에서 아래처럼
* 재정의를 해주어야만 합니다.
* date: 2000-12-05
*/
#define DEBUG_NORMALBLOCK new ( _NORMAL_BLOCK, __FILE__, __LINE__ )
#ifdef new
#undef new
#endif
#define new DEBUG_NORMALBLOCK
#else
// Send all reports to DEBUG window
_CrtSetReportMode( _CRT_WARN,
_CRTDBG_MODE_DEBUG );
_CrtSetReportMode( _CRT_ERROR,
_CRTDBG_MODE_DEBUG );
_CrtSetReportMode( _CRT_ASSERT,
_CRTDBG_MODE_DEBUG );
#endif
#ifdef malloc
#undef malloc
#endif
/*
* malloc으로 할당된 메모리에 누수가 있을 경우 위치
를 덤프
* CONSOLE 모드일 경우 crtdbg.h에 malloc이 정의되어
있지만,
* _AXFDLL 모드일 경우에는 약간 다른방식으로 덤프 하
게된다.
* date: 2001-01-30
*/
#define malloc(s) (_malloc_dbg( s, _NORMAL_BLOCK, __FILE__, __LINE__ ))
}
};
// 몇 가지 초기화를 생성자를 통해 자동으로 해주기 위해 전역으로 선언한다.
static __AutoDetectMemoryLeak __autoDetectMemoryLeak;
#endif // if defined(_MSC_VER) && defined (_DEBUG)
#endif // __AutoDetectMemoryLeak_h__
메모리 누수
#if !defined (__AutoDetectMemoryLeak_h__)
#define __AutoDetectMemoryLeak_h__
#if defined(_MSC_VER) && defined (_DEBUG)
#define _CRTDBG_MAP_ALLOC // 메모리 누수를 탐지하기 위해 선언 해주어야 한다.
#include <crtdbg.h>
#if !defined (_CONSOLE)
#include <cstdlib> // for Consol Application
#endif
class __AutoDetectMemoryLeak
{
public:
__AutoDetectMemoryLeak ()
{
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF |
_CRTDBG_LEAK_CHECK_DF);
// Consol Application인 경우
#if defined (_CONSOLE)
// Send all reports to STDOUT
_CrtSetReportMode( _CRT_WARN,
_CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN,
_CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR,
_CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR,
_CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT,
_CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT,
_CRTDBG_FILE_STDOUT );
/* new로 할당된 메모리에 누수가 있을 경우 소스상의
정확한 위치를 덤프해준다.
* ※ _AFXDLL을 사용할때는 자동으로 되지만 CONSOLE
모드에서 아래처럼
* 재정의를 해주어야만 합니다.
* date: 2000-12-05
*/
#define DEBUG_NORMALBLOCK new ( _NORMAL_BLOCK, __FILE__, __LINE__ )
#ifdef new
#undef new
#endif
#define new DEBUG_NORMALBLOCK
#else
// Send all reports to DEBUG window
_CrtSetReportMode( _CRT_WARN,
_CRTDBG_MODE_DEBUG );
_CrtSetReportMode( _CRT_ERROR,
_CRTDBG_MODE_DEBUG );
_CrtSetReportMode( _CRT_ASSERT,
_CRTDBG_MODE_DEBUG );
#endif
#ifdef malloc
#undef malloc
#endif
/*
* malloc으로 할당된 메모리에 누수가 있을 경우 위치
를 덤프
* CONSOLE 모드일 경우 crtdbg.h에 malloc이 정의되어
있지만,
* _AXFDLL 모드일 경우에는 약간 다른방식으로 덤프 하
게된다.
* date: 2001-01-30
*/
#define malloc(s) (_malloc_dbg( s, _NORMAL_BLOCK, __FILE__, __LINE__ ))
}
};
// 몇 가지 초기화를 생성자를 통해 자동으로 해주기 위해 전역으로 선언한다.
static __AutoDetectMemoryLeak __autoDetectMemoryLeak;
#endif // if defined(_MSC_VER) && defined (_DEBUG)
#endif // __AutoDetectMemoryLeak_h__
/////////////////////////////////////////////////////////////////////////////
/*Log.h*/
#define MAX_BUFFER_LENGTH 1024
class CLog
{
public:
// 생략기호(ellipsis)인...는 컴파일러에게 이후의 인수에 대해서는 개수와 타입을 점검하지 않도록 한다. 이 기호에 의해 가변인수를 사용할 수 있다.
static BOOL WriteLog(LPTSTR data, ...)
{
SYSTEMTIME SystemTime;
TCHAR CurrentDate[32] = {0, };
TCHAR CurrentFileName[MAX_PATH] = {0, };
FILE* FilePtr = NULL;
TCHAR DebugLog[MAX_BUFFER_LENGTH] = {0, };
TCHAR Log[MAX_BUFFER_LENGTH] = {0, };
// va_list = char*형, 가변인수를 읽기 위해 포인터변수를 선언했다고 생각하면 된다.
va_list ap;
// va_start(가변인수, 마지막 고정변수)
// 가변인수 ap를 고정변수data 다음의 메모리에 올리고 초기화한다.
// va_arg(ap, 인자타입) 인자타입을 받아 ap부터 반복적으로 다음 인자를 리턴한다.
va_start(ap, data);
// 로그에 데이터를 입력한다.
_vstprintf_s(Log, _countof(Log), data, ap);
// va_end(ap) 가변인수를 다 읽은 후 뒷정리한다.
va_end(ap);
// 시스템시간 가져오기
GetLocalTime(&SystemTime);
// 현재 데이터변수에 현재 시간을 저장한다.
_sntprintf_s(CurrentDate, _countof(CurrentDate), 32, _T("%02d-%02d-%02d %02d:%02d:%02d"),
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond);
// 현재 파일이름을 저장한다.
_sntprintf_s(CurrentFileName, _countof(CurrentFileName), MAX_PATH, _T("LOG_%04d-%02d-%02d %02d.txt"),
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour);
// 파일이 없으면 파일을 생성하고 파일이 있으면 존재하는 파일내용 다음에 쓴다.
_tfopen_s(&FilePtr, CurrentFileName, _T("a"));
// 생성이 되지 않으면
if(!FilePtr)
return FALSE;
// 파일에 현재 날짜와 로그를 입력한다.
_ftprintf(FilePtr, _T("[%s] %s\n"), CurrentDate, Log);
// 디버그 로그에 현재 날짜와 로그를 입력한다.
_sntprintf_s(DebugLog, _countof(DebugLog), MAX_BUFFER_LENGTH, _T("[%s] %s\n"), CurrentDate, Log);
// 버퍼를 해제한다.
fflush(FilePtr);
// 파일을 닫는다.
fclose(FilePtr);
// 디버그 로그를 출력한다.
OutputDebugString(DebugLog);
_tprintf(_T("%s\n"), DebugLog);
return TRUE;
}
};
////////////////////////////////////////////////////////////////////////////////////
#include <queue>
#include <deque>
//
// 배열 내용 값 순서
// 0 1 2
// 3 4 5
// 6 7 8
//
// 찾는 순서
// 0: 왼쪽, 1:위쪽, 2:오른쪽, 3:아래쪽
class Puz
{
public:
enum { MAX_PUZ = 9 };
enum PUZ_DIRECTION { PUZ_LEFT = 0, PUZ_UP, PUZ_RIGHT, PUZ_DOWN, PUZ_DIRECTION_MAX };
Puz()
:m_pParant(NULL), m_nDeep(0)
{
for(int i = 0; i < MAX_PUZ; ++i)
m_nPuz[i] = 0;
for(int i = 0; i < 4; ++i)
m_nNotMove[i] = true;
}
Puz* m_pParant;
int m_nPuz[MAX_PUZ];
int m_nDeep;
bool m_nNotMove[PUZ_DIRECTION_MAX];
void SwapPuz( int _nIndex1, int _nIndex2 )
{
int nTemp = m_nPuz[_nIndex1];
m_nPuz[_nIndex1] = m_nPuz[_nIndex2];
m_nPuz[_nIndex2] = nTemp;
}
bool EqualPuz( Puz* _p )
{
for(int i = 0; i < MAX_PUZ; ++i)
{
if( this->m_nPuz[i] == _p->m_nPuz[i] )
{
}
else
{
return false;
}
}
return true;
}
int SearchZero()
{
for( int i = 0; i < MAX_PUZ; ++i )
{
if( 0 == m_nPuz[i] )
return i;
}
CCLog( "SearchZero() Error!" );
return -1;
}
bool CanMove( int _eVal )
{
switch( _eVal )
{
case PUZ_LEFT:
{
int nZero = SearchZero();
if( 0 == nZero || 3 == nZero || 6 == nZero )
return false;
}
break;
case PUZ_UP:
{
int nZero = SearchZero();
if( 0 == nZero || 1 == nZero || 2 == nZero )
return false;
}
break;
case PUZ_RIGHT:
{
int nZero = SearchZero();
if( 2 == nZero || 5 == nZero || 8 == nZero )
return false;
}
break;
case PUZ_DOWN:
{
int nZero = SearchZero();
if( 6 == nZero || 7 == nZero || 8 == nZero )
return false;
}
break;
}
return m_nNotMove[_eVal];
}
Puz* NodeExpention( int _eVal )
{
Puz* pRt = new Puz;
pRt->m_nDeep = this->m_nDeep + 1;
pRt->m_pParant = this;
for(int i = 0; i < 9; ++i)
pRt->m_nPuz[i] = this->m_nPuz[i];
int nReversal;
switch( _eVal )
{
case PUZ_LEFT:
{
nReversal = PUZ_RIGHT;
break;
}
case PUZ_UP:
{
nReversal = PUZ_DOWN;
break;
}
case PUZ_RIGHT:
{
nReversal = PUZ_LEFT;
break;
}
case PUZ_DOWN:
{
nReversal = PUZ_UP;
break;
}
default:
CCLog("NodeExpention( int _eVal ) Error!");
break;
}
pRt->m_nNotMove[nReversal] = false;
int nZero = SearchZero();
switch( _eVal )
{
case PUZ_LEFT:
{
pRt->SwapPuz(nZero, nZero - 1);
break;
}
case PUZ_UP:
{
pRt->SwapPuz(nZero, nZero - 3);
break;
}
case PUZ_RIGHT:
{
pRt->SwapPuz(nZero, nZero + 1);
break;
}
case PUZ_DOWN:
{
pRt->SwapPuz(nZero, nZero + 3);
break;
}
}
return pRt;
}
};
#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 이면 서머타임 없음
}
다음과 같은 .reg파일을 만들어 레지스트리에 등록하면 .svn폴더를 지워주는 메뉴가 우클릭 팝업에 추가됨.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]
@="Delete SVN Folders"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""