::NPTEAM:: Network Programer Team

검색 :
RSS 구독 : 글 / 댓글 / 트랙백 / 글+트랙백

[STL] STL Container 자료구조 순환 삭제를 위한 코드

STL Container 자료구조 순환 삭제를 위한 코드

컨테이너가 표준 시퀀스 컨테이너이면, 컨테이너 요소를 하나씩 사용하는 루프를 작성합니다.
(erase를 호출할 때마다 그 함수의 반환값으로 반복자를 업데이트 하는 일을 꼭 해야 합니다.)

컨테이너가 표준 연관 컨테이너이면, 컨테이너 요소를 하나씩 사용하는 루프를 작성합니다.
(erase를 호출하면서 erase에 넘기는 반복자를 후위 증가 연산자로 증가시킵니다.)

(출처 : Effective STL p88)

팁 : erase() 함수의 리턴값이 있으면 반환값을 받고, 없으면 후위 증가 연산자로 증가시킵니다.

// std::vector 순환 삭제 코드
typedef std::vector< int > VEC_Container;
VEC_Container vecContainer;

vecContainer.push_back( 1 );
vecContainer.push_back( 2 );
vecContainer.push_back( 3 );
vecContainer.push_back( 4 );
vecContainer.push_back( 5 );

VEC_Container::iterator it = vecContainer.begin();
for( ; it != vecContainer.end(); )
{
	// erase 코드
	if( TRUE /*FALSE*/ )
	{
		it = vecContainer.erase( it );
		continue;
	}
	
	++it;
}


// std::list 순환 삭제 코드
typedef std::list< int > LIST_Container;
LIST_Container listContainer;

listContainer.push_back( 1 );
listContainer.push_back( 2 );
listContainer.push_back( 3 );
listContainer.push_back( 4 );
listContainer.push_back( 5 );

LIST_Container::iterator it = listContainer.begin();
for( ; it != listContainer.end(); )
{
	// erase 코드
	if( TRUE /*FALSE*/ )
	{
		it = listContainer.erase( it );
		continue;
	}
	
	++it;
}


// std::map 순환 삭제 코드
typedef std::map< int, int > MAP_Container;
MAP_Container mapContainer;

mapContainer.insert( std::make_pair(1, 5) );
mapContainer.insert( std::make_pair(2, 4) );
mapContainer.insert( std::make_pair(3, 3) );
mapContainer.insert( std::make_pair(4, 2) );
mapContainer.insert( std::make_pair(5, 1) );

MAP_Container::iterator it = mapContainer.begin();
for( ; it != mapContainer.end(); )
{
	// erase 코드
	if( TRUE /*FALSE*/ )
	{
		mapContainer.erase( it++ );
		continue;
	}
	
	++it;
}
2009/11/30 21:52 2009/11/30 21:52

맨 위로

간단한 Doxygen 사용 방법

2009/11/29 16:30, 글쓴이 TTF

프로그래밍과 문서화, 문서화와 프로그래밍...
프로그래머를 직업으로 가진 사람들은 한정된 시간에 프로그래밍 결과물과 문서화를 동시에 이루어야 하는 숙명을 지니고 살아간다.

이 두마리 토끼를 한번에 잡을 수 있을까?
한번에 두마리 토끼를 잡으려면, 토끼 한마리를 잡은 다음 토끼가 친구를 데려오게 하는 방법이 좋다.(-_-;)

Doxygen은 주석을 문서화 해주는 측면에서 매우 유용하다. 쓸만하다. 좋다.... 라는 평은 많이 들었지만,
실제로 사용하기 전에는 약간은 망설이게 된다.

이제부터 Doxygen 사용법에 대해서 알아보자.
http://www.stack.nl/~dimitri/doxygen/ 여기에서 Doxygen을 다운로드 받는다.
doxygen-1.6.1-setup.exe 파일을 실행하여 설치한다.

그래프 구조로 보기 위해서
http://www.graphviz.org/Download..php 여기에서 graphviz를 다운로드 받는다.
graphviz-2.24.msi 파일을 실행하여 설치한다.

이제 모든 준비는 끝났다.
"C:\Program Files\doxygen\bin\doxywizard.exe" 를 실행한다.



위와 같이 설정후 Run을 누르면,
D:\Project\TEST_CODE\Document\html\index.html 로 다음과 같은 출력물을 볼 수 있다.

기본적인 출력만 하더라도 노력한 결과에 비해서 상당히 예쁜(프로그래머 입장에서) 결과물을 볼 수 있었다.

http://www.atomineer.com/AtomineerUtils.html 에서 atomineer 플러그인을 설치하면,
비주얼 스튜디오에서 다음의 메뉴가 활성화 된다.

위 플러그인을 이용해서 함수와 클래스에 약간의 설명을 추가해 보도록 한다.

2009/11/29 16:30 2009/11/29 16:30

맨 위로

[C++] ReturnMacro

C++ 코드 작성시 가독성과 흐름처리를 원활하게 하기 위해서 다음과 같이 리턴 처리를 자주하게 된다.

bool LogicProcedure()
{
    if( A_Logic )
    {
        return false;
    }

    if( B_Logic )
    {
        return false;
    }

    return true;
}
위와 같이 중간에 흐름제어를 하기 위해서 try catch를 쓰고 싶어진다.

이를 해결하기 위해서 ReturnMacro를 작성하였다.

프로그래머에게 금기시되는 goto 제어문을 define으로 감싸서
1. 코드 가독성
2. 사용자 편의
3. 성능상의 잇점
3가지를 모두 얻을 수 있도록 헤더 파일을 제작하였다.



#pragma once

#include < strsafe.h >

//////////////////////////////////////////////////////////////////////////
// ReturnMacro For Singleton Class
template < typename T >
class CReturnMacroForSingleton
{
public:
	static T * InstancePtr()
	{
		if( ms_Instance == NULL ) ms_Instance = new T;
		return ms_Instance;
	};
	static T & Instance()
	{
		if( ms_Instance == NULL ) ms_Instance = new T;
		return *ms_Instance;
	};
	static void DestroyInstance()
	{
		delete ms_Instance;
		ms_Instance = NULL;
	};

private:
	static T * ms_Instance;
};

template< typename T > T* CReturnMacroForSingleton::ms_Instance = 0;
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
class CReturnMacro : public CReturnMacroForSingleton< CReturnMacro >
{
public:
	explicit CReturnMacro()
		: m_nGetLastLine(0)
	{
		memset( m_tszFunctionName, 0, sizeof( m_tszFunctionName ) );
	};

	~CReturnMacro() {};

public:
	inline int	GetLastLine()							{ return m_nGetLastLine;		}
	inline void	SetLastLine( int nLine )				{ m_nGetLastLine = nLine;		}

	inline TCHAR* GetFunctionName()						{ return m_tszFunctionName;		}
	inline void	  SetFunctionName( TCHAR* ptszFnName )
	{
		if( FAILED( StringCchCopy( m_tszFunctionName, _countof( m_tszFunctionName ), ptszFnName ) ) )
		{
			memset( m_tszFunctionName, 0, sizeof( m_tszFunctionName ) );
		}
	}

private:
	int		m_nGetLastLine;
	TCHAR	m_tszFunctionName[256];
};

#define RETURNMACRO CReturnMacro::Instance()
//////////////////////////////////////////////////////////////////////////


struct RETURN_RESULT
{
	int		LastLine;
	TCHAR*	LastFnName;
};

#define RETURN_VOID

//////////////////////////////////////////////////////////////////////////
// RETURN FAIL
#define RETURN_FAIL()													\
	RETURNMACRO.SetLastLine( __LINE__ );								\
	RETURNMACRO.SetFunctionName( _T(__FUNCTION__) );					\
	goto RET_FAIL;

#define RETURN_FAIL_BEGIN()												\
	RET_FAIL:															\
	RETURN_RESULT Ret_Fail;												\
	Ret_Fail.LastLine	= RETURNMACRO.GetLastLine();					\
	Ret_Fail.LastFnName = RETURNMACRO.GetFunctionName();

#define RETURN_FAIL_END( ReturnValue )									\
	return ReturnValue;
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// RETURN_SUCCESS
#define RETURN_SUCCESS( )												\
	RETURNMACRO.SetLastLine( __LINE__ );								\
	RETURNMACRO.SetFunctionName( _T(__FUNCTION__) );					\
	goto RET_SUCCESS;

#define RETURN_SUCCESS_BEGIN()											\
	RET_SUCCESS:														\
	RETURN_RESULT Ret_Success;											\
	Ret_Success.LastLine   = RETURNMACRO.GetLastLine();					\
	Ret_Success.LastFnName = RETURNMACRO.GetFunctionName();

#define RETURN_SUCCESS_END( ReturnValue )								\
	return ReturnValue;
//////////////////////////////////////////////////////////////////////////


Visual Assist Snippet code
RETURN_SUCCESS();


#pragma region RETURN_MACRO

	RETURN_FAIL_BEGIN();
	// Fail Code.
	RETURN_FAIL_END( RETURN_VOID );

	RETURN_SUCCESS_BEGIN();
	// Success Code.
	RETURN_SUCCESS_END( RETURN_VOID );

#pragma endregion RETURN_MACRO
2009/11/21 22:22 2009/11/21 22:22

맨 위로

[WMI] 프로세스 (시작 / 종료) 이벤트 발생시 프로그램 실행하기

프로세스 시작/종료 이벤트시에 하고 싶은 것들이 많다.
서버 프로그래머라면 서버 프로그램이 이유없이 죽을때 시간 및 Log를 남길 수도 있고,
프로그램이 죽으면, 다시 시작하도록 설정해서 24시간 스스로 유지되길 바라는 경우가 있다.
이럴때 윈도우에서 실행가능한 VBS(WMI)스크립트로 간단하게 관리해 보자.

아래의 스크립트는 다음과 같은 작동을 합니다.
1. 무한 루프를 반복하면서 1초마다 프로세스가 생성되거나 삭제되는 이벤트를 감시한다.
2. notepad.exe 프로세스가 생성되면, calc.exe를 실행합니다.
3. notepad.exe 프로세스가 삭제되면, calc.exe를 종료합니다.


Option Explicit

Dim strComputer
strComputer = "."

'기본 Object 가져오기
Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
Dim objWMIService : Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Dim colMonitorCreateProcessesEvent : Set colMonitorCreateProcessesEvent = objWMIService.ExecNotificationQuery("select * from __InstanceCreationEvent within 1 where TargetInstance isa 'Win32_Process'" )
Dim colMonitorDeleteProcessesEvent : Set colMonitorDeleteProcessesEvent = objWMIService.ExecNotificationQuery("select * from __InstanceDeletionEvent within 1 where TargetInstance isa 'Win32_Process'" )

'CMD 윈도우 98에서도 적용 가능하게 COMSPEC으로 가져온다.
Dim COMSPEC : COMSPEC = Shell.ExpandEnvironmentStrings("%comspec%")

'메인 함수 실행
Call MainFunction()


Sub MainFunction
	'중복 실행 방지 코드 - vbs 파일명을 입력합니다.
	If( IsExistSameVBS( "ProcessEvent.vbs" ) ) Then
		Wscript.Quit
	End If
	
	Do While True
		Call ProcessCreatedEvent()
		Call ProcessDeletedEvent()
		Wscript.Sleep( 1000 )
	Loop
	
	Wscript.Quit
End Sub


Sub ProcessCreatedEvent
	'프로세스 시작시
	
	'모니터링할 프로세스 이름
	Dim strMonitorProcessName : strMonitorProcessName = "notepad.exe"
	
	'실행할 파일
	Dim strExecuteFilePath : strExecuteFilePath = "C:\Windows\system32"
	Dim strExecuteFileName : strExecuteFileName = "calc.exe"
	
	'프로세스 시작 이벤트 검사
	Dim objLastestProcess : Set objLastestProcess = colMonitorCreateProcessesEvent.NextEvent
	If( StrComp(Lcase(objLastestProcess.TargetInstance.Name), Lcase(strMonitorProcessName), 1 ) = 0 ) Then
		'프로그램 실행
		Call ExecuteOnce( strExecuteFilePath, strExecuteFileName, "" )
	End If
End Sub


Sub ProcessDeletedEvent
	'프로세스 종료시
	
	'모니터링할 프로세스 이름
	Dim strMonitorProcessName : strMonitorProcessName = "Notepad.exe"
	
	'종료할 프로세스 이름
	Dim strKillProcessName : strKillProcessName = "calc.exe"
	
	'프로세스 종료 이벤트 검사
	Dim objLastestProcess : Set objLastestProcess = colMonitorDeleteProcessesEvent.NextEvent
	If( StrComp(Lcase(objLastestProcess.TargetInstance.Name), Lcase(strMonitorProcessName), 1) = 0 ) Then
		'프로세스 종료
		Call KillProcess( strKillProcessName )
	End If
End Sub


Sub ExecuteFile (strFileFullPath, Arguments)
	If( FSO.FileExists( strFileFullPath ) ) Then
		Shell.Run COMSPEC & " /c " & strFileFullPath & Arguments & " & Exit", 0
	Else
		Shell.Popup strFileFullPath & " 을(를) 찾을 수 없습니다.", 3, "File Dose not exist", 48
		Wscript.Quit
	End If
End Sub


Function IsExistProcess( strProcessName )
	IsExistProcess = False
	
	Dim colProcessList, objProcess
	Set colProcessList = objWMIService.ExecQuery( "select * from Win32_Process" )
	For Each objProcess in colProcessList
		If( StrComp(Lcase(strProcessName), Lcase(objProcess.Name), 1) = 0 ) Then
			IsExistProcess = True
		End If
	Next
End Function


Sub ExecuteOnce( strFilePath, strFileName, Arguments )
	If( IsExistProcess( strFileName ) = False ) Then
		Call ExecuteFile( strFilePath & "\" & strFileName, Arguments )
		Wscript.Sleep 2000
	End If
End Sub


Sub KillProcess( strProcessName )
	Dim colProcessList, objProcess
	Set colProcessList = objWMIService.ExecQuery( "select * from Win32_Process" )
	For Each objProcess in colProcessList
		If( StrComp(Lcase(strProcessName), Lcase(objProcess.Name), 1) = 0 ) Then
			objProcess.Terminate()
		End If
	Next
End Sub


Function IsExistSameVBS( strFileName )
	IsExistSameVBS = False
	Dim nSameVBSCount : nSameVBSCount = 0
	
	Dim colProcessList, objProcess
	Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'wscript.exe' OR Name = 'cscript.exe'")
	For Each objProcess in colProcessList
		If InStr( Lcase(objProcess.CommandLine), Lcase(strFileName) ) Then
			nSameVBSCount = nSameVBSCount + 1
		End If
	Next
	
	If( nSameVBSCount > 1 ) Then
		IsExistSameVBS = True
		Wscript.echo strFileName & " 은 이미 실행중인 스크립트 입니다."
	End If
End Function
2009/11/06 21:53 2009/11/06 21:53

맨 위로