블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

#define 과 얼핏 비슷해 보이지만비슷한 유형별의 데이터를 표현하기 위해 반드시 필요한 C++의 필수 타입인 enum 의 몇 가지 재미있고 유용한 팁을 소개합니다.

 

1. namespace 와 결합하기

 

일반적으로 enum 을 이용하여 타입이름을 짓기란 쉬운 일이 아닙니다.

만약 리스트에 필요한 정렬 기준을 enum 으로 표현한다면 아래 정도가 됩니다.

 

enum SORT_LIST

{

           SORT_DATE,                 // 날짜순

           SORT_NAME,                // 이름

           SORT_CONTENT, // 내용

           S0RT_ETC,                    // 기타

};        

 

bool SortSomeData(SORT_LIST SortList)

{

           switch (SortList)

           {

           case SORT_DATE:

                     break;

           case S0RT_NAME:

                     break;

           // ....

           }

}

 

 

하지만이러한 enum 표현 방식은

  •  SORT_DATE 라는 이름은 너무 흔합니다.  프로그램이 조금만 커져도 이러한 이름들이 다른 곳에서도 필요하게 되어 이름 충돌을 피하기 힘들어 집니다.  이름 충돌을 피하기 위해서는 SORT_LIST를 변경해도 아무런 소용이 없고 SORT_DATE 를 완전히 다른 이름으로 지어야만 합니다.
  • enum 의 타입이름인 SORT_LIST와 실제 값인 SORT_DATE 를 서로 연관 짓기가 힘듭니다. switch 문 내에서도 타입이름(SORT_LIST)은 사용되지 않아서 SORT_DATE만 보고 이 값이 SORT_LIST 의 한 유형인지 구분 짓기 힘듭니다
  • enum 값에 항상 들어 있는 SORT 라는 prefix 도 부담스럽습니다. SORT_XXX 식으로 이름을 짓다 보니타입핑하기도 힘들구요

 

평소 이런 문제에 대해서 알고는 있었지만 그 해결책을 고민만 하던 차에 아주 좋은 해결책을 발견했습니다바로 아래 글에서요. (늘 해결책은 제가 아닌 책이나 다른 글에서 구합니다.)

 

Stupid C++ Tricks #2: Better Enums

 

이 글에서 제안하는 방식은 enum  namespace과 결합하여 가독성을 증가 시키고이름충돌도 최소화시키는 방식입니다. 위에 든 예를 namespace 식으로 표현하면 다음과 같습니다.

 

namespace SortList

{

           enum Enum

           {

                     BytDate, // 다가올날기준

                     ByName,                     // 이름

                     ByContent,        // 내용

                     Etc,

           };        

}

 

bool SortSomeData(SortList::Enum SortList)

{

           switch (SortList)

           {

           case SortList::ByDate:

                     break;

           case SortList::ByName:

                     break;

           // ....

           }

}

 

namespace 와 결합함으로써, enum 의 각 항목에는 항상 SortList 라는 namespace가 따라 붙게 되어 가독성이 증가함을 알 수 있습니다SORT_DATE  보다는 SortList::ByDate 가 읽기 쉽고요즘 웬만한 IDE 에서는 namespace SortList::만 입력하면 자동으로 이하 소속되는 타입이름들이 나열되기 때문에 미스타이핑 할 가능성도 줄여주네요.


사용자 삽입 이미지


게다가 namespace 를 사용하기 때문에 다른 모듈과 이름이 충돌할 가능성도 줄어들었습니다.

이름 충돌이 없기 때문에 아래와 같이 NameEdit 라는 enum 값을 여러 namespace 에 걸쳐 사용하면서 각각의 의미에 맞는 값들을 줄 수가 있게 됩니다.

 

namespace ControlWidth

{

           enum Enum

           {

                     NameEdit = 20,

                     AddressCombo = 60,

                     OkBtn = 30;

                     // ....

           };

};

 

namespace ControlID

{

           enum Enum

           {

                     NameEdit = 100,

                     AddressCombo = 101,

                     OkBtn = 102;

                     // ....

           };

}

 

이와 같이 enum 을 표시하는 방식은 실제 꽤 유용하게 써 먹을 수 있어서 지금 새로 만들고 있는 프로젝트에서도 재작성하는 코드에서 enum 타입을 위 방식으로 변경하고 있는 중입니다.

괜찮은 방법 아닌가요 ? ^^;

 

 

2.  enum 에 문자열 결합하기


2번째 팁은 숫자로만 되어 있는 enum 을 문자열로 치환하는 팁입니다.

C++ 에서 enum 을 정수형으로만 치환가능하기 때문에 사용자가 읽을 수 있는 텍스트로 변경하기 위해서는 enum 값에 1:1 매칭되는 텍스트가 필요한 경우가 많습니다.

이를 해결하는 방법으로 아래 포스팅에서는 enum  #define 매크로를 이용해서 문자열을 매칭시키는 방법을 소개합니다.

 

Enums, Macros, Unicode and Token-Pasting

 

Visual C++ Team Blog 에 소개된 이 방법은 숫자로이뤄진 enum 값과

 

enum Animal { dog, cat, fish, bird };

 

문자로이뤄진char값을매칭시키는방안에대한내용입니다.

 

wchar_t* AnimalDiscription[] = { L"dog", L"cat", L"fish", L"bird" };

 

이를 위해 animal.inc 파일에 아래 라인들을 추가하고

 

MYENUM(dog)

MYENUM(cat)

MYENUM(fish)

MYENUM(bird)

 

아래와 같이 enum 을 선언합니다.

 

enum Animal {

#define MYENUM(e) _##e,

#include "animal.inc"

#undef MYENUM

};

 

wchar_t* AnimalDescription[] = {

#define MYENUM(e) L"_" L#e,

#include "animal.inc"

#undef MYENUM

};

 

#define 으로 조금 복잡해 보여서 그렇지, enum 값과 wchar_t* 배열의 선언을 MYENUM 매크로 정의를 통해 확장하는 식입니다.  조금 특이한 것은 MYENUM  enum  wchar_t* 배열 속에서 조금씩 다르게 선언하고데이터를 추가한 후( #include "animal.inc") 에는 바로 undefined 시켜버리는 정도네요

 

이 방법 마음에 드시나요?

해당 링크에 달린 댓글들을 보면 많은 분들이 마음에 들지 않나 봅니다.

가장 크게 문제 삼은 내용은 역시 아래 글과 같은 #define 매크로에 대한 조금 헤묵은 논쟁들입니다.

 

Macros is something C++ (especially the Standards Committee) has always tried to avoid. Such use of macros like this will make code unreadable and cause maintainance problems. I think it's not a good idea to play with such thing.

 

개인적으로는 #define 을 활용한 매크로 활용을 좋게 보고 있습니다.

제가 #define을 좋아하는 이유는

  • 코딩량을 줄여 줍니다코딩하는 량이 줄어든다는 것은 그만큼 유지관리할 코드가 줄어 들고미스타이핑에 의한 작은 실수들을 걸러주기 때문입니다.
  • 자주 해야 하지만 귀찮은 작업들 - Get/Set 함수 같은 - 을 쉽게 처리해 줍니다저 같은 경우 클래스 하나를 만들면 대부분은 private 멤버변수들이어서 늘 public 으로 Get/Set 함수를 구현하는 게 고역 중에 고역인데요.  #define 매크로를 활용하면 늘 심플하고 코드 보기도 편하더군요.


Visual C++ 에 있는 _countof 매크로도 정말 없어서는 안될 매크로 중 하나입니다.

 

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

}

 

아무튼논란의 여지가 있긴 하지만이 팁의 주요 목적은 enum Type 으로 추가할 숫자값과문자열 값이 어느 하나만 추가되거나삭제되지 않고 늘 한번에 관리 될 수 있도록 하기 위한 방안 중에 하나라고 봅니다.  유용했다면 쓰면 될 것이고 그렇지 않으면 안 쓰면 되겠죠 :-)

댓글 중에는 하나의 .inc  include 할 필요 없이 하나의 파일에서 모두 해결하는 방안도 있으니 참고하세요

 

#define ANIMALS(FOO) \

FOO(dog) \

FOO(fish) \

FOO(cat)

 

#define DO_DESCRIPTION(e)  L"_" L#e,

#define DO_ENUM(e)  _##e,

 

wchar_t* AnimalDescription[] = {

ANIMALS(DO_DESCRIPTION)

};

 

enum Animal {

ANIMALS(DO_ENUM)

};

 

 

3.  enum 의 처음과 끝을 지정하자

 

1, 2번에 비하면 좀 약한 팁입니다만, enum 을 사용할 때 처음과 끝을 지정하자는 아이디어는 Code Complete 2 책에 p436에 나와있습니다.

아래와 같은 국가명을 열거할 필요가 있을 때처음과 끝에 해당하는 값을 XXX_FIRST 와 XXX_LAST로 지정하는 방법입니다.

 

enum Country

{

           Country_First = 0,

           Country_China = 0,

           Country_England = 1,

           Country_France = 2,

           Country_Germany = 3,

           Country_India = 4,

           Country_Korea = 5,

           Country_Japan = 6,

           Country_Usa = 7,

           Country_Last = 7,

};

 

XXX_FIRST 와 XXX_LAST 가 시작과 끝을 가르키기 때문에 이를 활용하여 열거형의 모든 항목을 조회하여 원하는 일을 할 때 유용합니다.

 

for (Country cty = Country_First; cty <= Country_Last; cty++)

{

           // 원하는로직수행

}

 

추후 새로운 국가 Country_Italy 를 추가한다면 아래와 같이 enum 만 수정하면 enum 을 사용하는 for loop 는 손대지 않아도 되는 장점이 생깁니다.

 

           Country_Usa = 7,

           Country_Italy = 8,

           Country_Last = 8,

}

 

이상 enum 을 활용하는 몇 가지 팁을 알아 봤습니다 혹시 나만의 좋은 팁이 있으시면 같이 공유해 주세요.


출처 : http://eslife.tistory.com/300

반응형
Posted by blueasa
, |

C++ 을 배운지 꽤 오래 되었지만, 아직도 코드 리뷰를 통해 다른 개발자들의 코드를 볼 때면 한숨이 나오는 경우가 많습니다.

이런 경우가 반복되다 보니, 예전에 몇 가지 코딩 규칙 비슷하게 만들어놓은 자료가 있어 포스팅해 봅니다.  자료가 만들다 말아 내용이 중구난방이네요..  앞으로도 계속 내용 보강해 나가겠습니다.

 

    포인트 핸들 및 윈도우 핸들 체크

-       함수로 전달된 포인터 인자나, new 로 생성한 포인터 등 모든 포인터는 사용하기 직전 포인터 검사를 수행

-       가급적 STL 컨테이너를 사용해서 아예 포인터를 사용하지 않는 것이 정신건강에 이롭다. (STL 자체적으로 메모리 생성 및 소멸)

-       메모리 LEAK 을 막기 위해 SMART POINT 와 같은 Wrapper 클래스를 만든다.

-       (윈도우 프로그램의 경우)윈도우 API 호출 직전 항상 윈도우 핸들이 정상인지 IsWindow 와 같은 함수로 검사한다.

 

    DRY(Don't Repeat Your Code)원칙

-       같은 코드를 여기 저기 중복해서 사용하지 말아야 한다. (☞ 실용주의 프로그래머 참고). 중복해서 사용할 경우 코드 량이 늘어날 뿐만 아니라 유지보수 cost 가 같이 늘어 나고, 추후 추가/개선/변경 등의 요구사항으로 인한 모듈 수정 시 여러 소스를 함께 수정해야 한다.

-       동일한 코드를 공용 루틴(함수)으로 개발 – 2~3줄 짜리 복잡한 if 문도 bool 를 리턴 하는 함수로 개발(Refactoring 참고)

 

    클래스간 종속성 최소화

-       대규모 프로젝트에서는 공통모듈이 변경되어도 이를 사용하는 모듈이 문제가 없도록 반드시 공통모듈은 인터페이스 기반(데이터가 없는, virtual 가상함수로만 구성된)으로 구현한다. (The C++ Programming Language 참고)

-       A 클래스 → B 클래스 → C 클래스를 사용할 경우 각 클래스는 자기가 직접 다루는 클래스(A B, B C) 만 알아야 한다. A 클래스는 C 클래스를 직/간접적으로 include 해서는 안되며 C 클래스의 변경으로 인해 A 클래스가 컴파일 되어서는 안 된다. A 클래스가 C 를 직접 접근할 경우가 있다면 B 클래스에 위임함수를 만들어 해결한다. (☞ 실용주의 프로그래머 참고)

-       B 클래스가 A 클래스로 어떤 데이터를 전달할 경우가 있다면(주로 이벤트 발생시 값을 전달하기 위해) A 클래스의 최소 인터페이스만을 B 클래스에 전달하여(COM 의 이벤트 소스 방식) 종속성을 최소화 한다. (Developer’s Workshop To COM and  ATL 3.0 참고)

 

    함수 인자 전달

-       함수의 인자는 최대 7개를 넘지 않아야 한다(Code Complete 2 참고)

-       클래스 인스턴스를 함수 인자로 넘겨서는 안 된다(특히 함수 인자로 CString 을 넘기는 경우가 많음. CString → const CString& CString*, const char* 등으로 수정한다. )

 

    오류조건을 먼저 검사하여 오류 체크로 인해 코드 가독성이 떨어지지 않도록 하자.

-       특정 오류조건이 발생하면 더 이상 함수 수행에 의미 없을 경우, 이러한 오류 조건들은 함수초입단계부터 먼저 확인해서 바로 리턴 한다

-       위와 같이 오류조건이 먼저 확인되면 프로그램 코드에서 if depth 가 줄어 들고 코드 읽기가 수월해 지는 장점이 있다.

Before

After

void CClass::OnTest()

{

 ...

 ...

 if (m_pWndMain)

 { 

  DoSomething1();

 }

 ...

 if (m_pWndMain)

 { 

  DoSomething2();

 }

 

}

void CClass::OnTest()

{

 if (m_pWndMain == NULL)

  return;

 ...

 ...

 DoSomething1();

 ...

 DoSomething2();

 

}

 

    긴 함수 쪼개기 (Refactoring 참고)

-       긴 함수는 작은 여러 개의 함수로 쪼갠다(Refactoring 책에 의하면 2-3줄 짜리 함수로까지 쪼개어서 코드 가독성을 높이도록 하고 있음)

-       작은 함수로 쪼개다 보면, 작은 함수를 재활용하게 될 수 있고

-       긴 함수보다 코드 읽기가 수월해 지며

-       결국 유지보수가 쉬워진다

 

    enum 값 선언 시 _START, _END 를 활용하자( CODE COMPLETE2 참고)

-       enum 으로 선언된 값들을 변수나 for loop 를 이용하여 반복 계산할 경우가 종종 있는데 이 경우 enum 시작과, 끝을 나타내는 값을 enum 선언에 포함하면 유용하게 사용할 수 있다.

-       추후 enum 에 값을 추가해야 할 경우 _END 값을 사용한 배열은 코드 변경없이 크기가 늘어남

-       For 루프 등에 _START, _END 을 사용할 수 있어 유지 보수에 유리

Before

After

enum WEEK_NAME

{

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

};

 

int nWeeks[SATERDAY + 1];

}

enum WEEK_NAME

{

           WEEK_STAR       = 0,

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

           WEEK_END        = 6,

};

 

int nWeeks[WEEK_END + 1];

 

 

    복잡한 제어문을 가진 루틴을 피하자  

-       If 문은 2 depth 이상 들어 갈 경우 refactoring 하라 (CODE COMPLETE2)

     대부분 코드를 제대로 이해하지 못해 복잡한 코드를 작성하고 있다.

     개발자 90% 2 depth 이상 들어가는 if 문장을 이해하지 못한다

-       IF~ELSE IF ~ELSE IF ~ …. ELSE 가 길게 이어질 경우 SWITCH 문으로 바꾼다

-       IF 문이 길게 늘어 질 경우 함수로 분리한다

-       C++ factory 개념으로 상속을 이용한 클래스를 만드는 방법도 활용


반응형
Posted by blueasa
, |

윈도우를 종료
System.Diagnostics.Process.Start("cmd.exe","ShutDown.exe -s -f -t 00");


윈도우를 재부팅

System.Diagnostics.Process.Start("cmd.exe","ShutDown.exe -r -f -t 00");

 

특정 폴더 열기
System.Diagnostics.Process.Start("explorer.exe", "C:\Temp");

특정 사이트 열기
System.Diagnostics.Process.Start("explorer.exe", "http://www.naver.com");

 

도스명령어 실행

System.Diagnostics.Process.Start("cmd.exe","/c dir");

// cmd 옵션에 대해 더 알고싶으면.. c:>help cmd

 

Process.Start 메서드 사용형식
 

using System.Diagnostics;

//System.Diagnostics 네임스페이스는 시스템 프로세스, 이벤트 로그 및 성능 카운터와 상호 작용할 수 있는 클래스를 제공합니다.

 

public bool Start();
//이 Process 구성 요소의 StartInfo 속성으로 지정된 프로세스 리소스를 시작하거나 다시 사용하여 구성 요소에 연결합니다.

 

Process myProcess = new Process();
string myDocumentsPath =   Environment.GetFolderPath(Environment.SpecialFolder.Personal);
myProcess.StartInfo.FileName = myDocumentsPath + "
\MyFile.doc"; 
myProcess.StartInfo.Verb = "Print";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();

 

public static Process Start( ProcessStartInfo startInfo);
// ProcessStartInfo : 파일 이름 및 모든 명령줄 인수를 포함하여 프로세스를 시작하는 데 사용되는 정보
// 시작할 프로세스의 파일 이름 같은 프로세스 시작 정보가 포함된 매개 변수에 의해 지정된 
// 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다

 

ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
startInfo.Arguments = "
www.naver.com";
Process.Start(startInfo);

 

public static Process Start(string fileName);
// fileName : 프로세스에서 실행될 응용 프로그램 파일 이름입니다.

//문서 또는 응용 프로그램 파일 이름을 지정하여 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다

 

Process.Start("IExplore.exe");

 

public static Process Start(string fileName, string arguments); 
// arguments : 프로세스를 시작할 때 전달할 명령줄 인수입니다

//응용 프로그램 이름 및 명령줄 인수 집합을 지정하여 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다.

 

Process.Start("IExplore.exe", "C:\myPath\myFile.htm");
Process.Start("IExplore.exe", "C:\myPath\myFile.asp");

 

 

Process 클래스

Process 구성 요소는 컴퓨터에서 실행 중인 프로세스에 대한 액세스를 제공합니다. 간단히 말해 프로세스란 실행 중인 응용 프로그램을 말합니다.

 

Process 구성 요소는 응용 프로그램의 시작, 중지, 제어 및 모니터링을 위한 유용한 도구입니다.
Process 구성 요소를 사용하면 실행 중인 프로세스의 목록을 얻거나 새로운 프로세스를 시작할 수 있습니다. 또한 Process 구성 요소를 사용하여 시스템 프로세스에도 액세스할 수 있습니다. 
Process 구성 요소를 초기화한 후에는 해당 구성 요소를 사용하여 실행 중인 프로세스에 대한 정보를 얻을 수 있으며 그러한 정보에는 스레드 집합, 로드된 모듈(.dll 및 .exe 파일), 프로세스가 사용하고 있는 메모리 양과 같은 성능 정보 등이 포함됩니다.

 

프로세스 구성 요소는 속성 그룹에 대한 정보를 한 번에 가져옵니다. Process 구성 요소가 특정 그룹의 한 멤버에 대한 정보를 가져올 때 해당 그룹의 나머지 속성 값이 캐싱되므로 Refresh 메서드를 호출하지 않는 한 그룹의 다른 멤버에 대한 새로운 정보를 가져오지 않습니다. 따라서 속성 값이 Refresh 메서드를 마지막으로 호출하여 얻은 속성 값과 같을 수 있습니다. 이러한 그룹 명세는 운영 체제에 따라 다릅니다.

 

더 자세한 사항은 Microsoft Visual Studio .NET 2003 도움말에서 Process 클래스를 참고하세요.

 

 

도스명령수행 프로그램 


 

[전체소스]


using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Diagnostics;

using System.IO;

using System.Threading;


namespace mouseEvents

{


    public class Form1 : System.Windows.Forms.Form

    {

        private System.Windows.Forms.TextBox textBox1;

        private System.Windows.Forms.Label label2;

        private System.ComponentModel.IContainer components;

        private System.Windows.Forms.TextBox tbComm;

        private System.Windows.Forms.Button btnExec;



        public Form1()

        {

            InitializeComponent();

        }


        protected override void Dispose( bool disposing )

        {

            if( disposing )

            {

                if (components != null)

                {

                    components.Dispose();

                }

            }

            base.Dispose( disposing );

        }


        #region Windows Form Designer generated code

        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()

        {

            this.label2 = new System.Windows.Forms.Label();

            this.tbComm = new System.Windows.Forms.TextBox();

            this.btnExec = new System.Windows.Forms.Button();

            this.textBox1 = new System.Windows.Forms.TextBox();

            this.SuspendLayout();

            //

            // label2

            //

            this.label2.Location = new System.Drawing.Point(8, 8);

            this.label2.Name = "label2";

            this.label2.Size = new System.Drawing.Size(72, 17);

            this.label2.TabIndex = 5;

            this.label2.Text = "도스명령어:";

            //

            // tbComm

            //

            this.tbComm.Location = new System.Drawing.Point(80, 8);

            this.tbComm.Name = "tbComm";

            this.tbComm.Size = new System.Drawing.Size(355, 21);

            this.tbComm.TabIndex = 6;

            this.tbComm.Text = "";

            //

            // btnExec

            //

            this.btnExec.Location = new System.Drawing.Point(440, 8);

            this.btnExec.Name = "btnExec";

            this.btnExec.Size = new System.Drawing.Size(104, 25);

            this.btnExec.TabIndex = 1;

            this.btnExec.Text = "실행";

            this.btnExec.Click += new System.EventHandler(this.button2_Click);

            //

            // textBox1

            //

            this.textBox1.AcceptsReturn = true;

            this.textBox1.AcceptsTab = true;

            this.textBox1.Location = new System.Drawing.Point(8, 32);

            this.textBox1.Multiline = true;

            this.textBox1.Name = "textBox1";

            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;

            this.textBox1.Size = new System.Drawing.Size(528, 312);

            this.textBox1.TabIndex = 2;

            this.textBox1.Text = "";

            //

            // Form1

            //

            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

            this.ClientSize = new System.Drawing.Size(547, 350);

            this.Controls.Add(this.tbComm);

            this.Controls.Add(this.label2);

            this.Controls.Add(this.textBox1);

            this.Controls.Add(this.btnExec);

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

            this.MaximizeBox = false;

            this.Name = "Form1";

            this.Text = "Process Class";

            this.ResumeLayout(false);


        }

        #endregion


        [STAThread]

        static void Main()

        {

            Application.Run(new Form1());

        }


        private void button2_Click(object sender, System.EventArgs e)

        {

            this.start();

        }


        private void start()

        {


            //Network 변수

            StreamWriter DosWriter;

            StreamReader DosRedaer;

            StreamReader ErrorReader;

           

            //프로세스 생성및 초기화

            Process DosPr = new Process();

           

            ProcessStartInfo psI = new ProcessStartInfo("cmd");

            psI.UseShellExecute = false;

            psI.RedirectStandardInput = true;

            psI.RedirectStandardOutput = true;

            psI.RedirectStandardError = true;

            psI.CreateNoWindow = true;



            //명령 실행

            DosPr.StartInfo = psI;

            DosPr.Start();

            DosWriter = DosPr.StandardInput;

            DosRedaer = DosPr.StandardOutput;

            ErrorReader = DosPr.StandardError;


            DosWriter.AutoFlush = true;


            DosWriter.WriteLine(tbComm.Text);

           

            DosWriter.Close();


            //출력

            textBox1.Text = DosRedaer.ReadToEnd();

            textBox1.Text += ErrorReader.ReadToEnd();


        }

    }

}



  작성자 : HOONS(박경훈)
  이메일 : tajopkh@hanmail.net

출처 : http://www.cyworld.com/nowy/192742


[출처 : http://skql.tistory.com/510]

반응형
Posted by blueasa
, |
반응형

'Etc' 카테고리의 다른 글

[M/V] Sunshine Girl  (0) 2011.03.31
저렴한 거북목 피는 스트레칭  (0) 2011.02.12
[펌] Getter/Setter 없는 삶  (0) 2010.11.10
집에 돌아오면 아내가 죽은척을 해요...  (0) 2010.10.28
[펌] 프로그래머에 관한글  (0) 2010.10.25
Posted by blueasa
, |

Programmers united develop net

Link / 2011. 1. 10. 17:03
반응형

'Link' 카테고리의 다른 글

Delta3D API Documentation  (0) 2011.01.25
Gamebryo 관련 사이트  (0) 2011.01.21
C# 배움터  (0) 2010.12.23
Download D3DX DLLs (d3dx9_xx.dll, d3dx10_xx.dll)  (0) 2010.12.23
종이천하  (0) 2010.12.20
Posted by blueasa
, |

Visual C++ (.NET 기준)에서 디버깅 시 유용하게 사용할 수 있는 컴파일옵션들을 정리해 보았습니다.  하나하나 다 외우질 못해 프린트해서 그때그때 사용하고 있습니다. ^^

도움이 될 지 모르겠네요.

 

/EP /P C/C++ Preprocessor Generate Preprocessed File
(파일전처리)
전처리 코드에 대한 내용을 소스파일.i 파일로 볼 수 있다. 
/C C/C++ Preprocessor Keep Comments
(주석유지)
위를 설정하고 이것도 설정하면 선택하면 전처리코드 위의 주석도 유지하면서 보여 줄 것이다.
/X C/C++ Preprocessor Ignore Standard Include Path
(표준 포함경로무시)
표준 인클루드 경로 무시
/Zp C/C++ Code Generation Struct Member Alignment
(구조체 맴버 맞춤)
#pragma pack 지시자를 사용하는 것이 더 좋을 것 같다.
/Wp64 C/C++ General Detect 64-bit Portability Issues
(64비트 이식성 문제 검색)
나중 64비트 호완성을 돕기위해 설정을 해 두는 것이 좋다.
/RTC C/C++ Code Generation Smaller Type Check
(작은 형식 검사)
/RTCc : 값을 작은 데이터 형식으로 변환할 때 데이터손실이 없는 지 검사한다.
Basic Runtime Checks
(기본 런타임 검사)
/RTCu : 초기화되지 않은 변수참조를 추적한다.
/RTCs : 모든 지역변수들을 0xCC로 초기화 하여 훌륭한 스택 프레임 검사가 로컬변수 언더런과 오버런을 감지하고 스택 충돌에 대해서 스택 포인터를 검증하도록 한다.
/RTCsu : 위의 두개 모두 포함
/GS C/C++ Code Generation Buffer Security Check
(버퍼 보안 검사)
바이러스 작성자들의 가장 일반적인 공격인 리턴주소를 악성코드로 리다이렉트 할 수 있도록 하는 버퍼오버런공격을 막아주는 것이다.
/O(num) C/C++ Optimization Optimization
(최적화)
/O1(크기최소화), /O2(속도최대화:디폴트)
마이크로소프트 제품은 모두 /O1으로 컴파일..이것으로 컴파일 할 때 같이 SWS(Smooth Working Set)유틸리티를 사용해서 공통적으로 사용하는 함수들을 앞으로 배치되도록 해야 한다.(속도도 높이기 위해)
/GL Main General Whole Program Optimization
(전체프로그램최적화)
설정하면 링커스위치에 /LTCG(밑에 참조 바람)를 설정
/showincludes C/C++ Advanced Show Includes
(포함 파일 나열)
컴파일 할 때 포함되는 include 파일들이 어떤 위치의 것인지를 Output 화면으로 모두 보여준다.
/MAP Linker Debugging Generate Map File
(맵파일 생성)
맵파일을 생성하는 스위치로 유용한 정보를 얻기위해서는 모두 사용해야 한다.
/MAP:LINES Linker Debugging Map Lines
(맵파일에 줄 번호 정보 포함
/MAP:EXPORTS Linker Debugging Map Exports
(맴파일에 익스포트 함수정보 포함)
/NODEFAULTLIB Linker Input Ignore All Default Libraries
(라이브러리 무시)
많은 시스템 헤더파일들이 어떤 파일이 링크되는지 지정하기 위해 #pragma comment (lib#,립이름)을 포함하는데 이를 모두 무시하도록 지시한다.
/OPT:NOWIN98 Linker Optimization Optimize for Windows98
(Windows98에 맞게 최적화)
98,ME를 지원하지 않는 다면 설정하는 것이 좋다. 응용프로그램의 크기를 줄일 수 있다.
/ORDER Linker Optimization Function Order
(함수에 순서 지정)
SWS(Smooth Working Set) 을 실행한 후 함수의 순서를 포함하고 있는 파일을 지정할 수 있다.
/VERBOSE Linker General Show Process
(진행 메시지 표시)
링크되는 라이브러리의 모든 진행 메세지를 표시
/VERBOSE:LIB Linker General Show Process
(진행 메시지 표시)
검색된 라이브러리만 나타내는 진행 메세지를 표시
/LTCG Main General Whole Program Optimization
(전체프로그램최적화)
/GL스위치와 짝을 이룬다. 링크시간코드를 생성.
/RELEASE Linker Advanced Set Checksum
(체크섬 설정)
별로 사용되지 않지만 WinDBG를 사용할 때 책섬을 조사할 때 필요하기 때문에 미리 넣어 두는 게 좋다.
/PDBSTRIPPED Linker Debugging Strip Private Symbols
(전용 기호 제거된 심볼)
스택을 탐색하고 해독하기 위해서 필요한 특별한 Frame Pointer Omission(FPO) 데이터를 PDB파일에 포함시키기 위해 설정한다. 각종 변수나 소스 줄정보는 빼고 필요한 FPO데이터와 공용함수들만 남겨놓는다(stripped PDB파일). 이것과 함께 일반 PDB 파일을 같이 생성할 수 있다. 나중에 Dr.Watson 등에서 PDB파일을 로드할 수 있기 위해서는 파일명을 어플리케이션 명과 같게 해줄 필요가 있다.

반응형
Posted by blueasa
, |

//////////////////////////////////////////////////////////

//VC++의 출력창을 이용한 디버깅 수단1

#include <Windows.h>

//void main()...

OutputDebugString(msg);                                         //VC출력창에 문자가 출력 된다.

 

//////////////////////////////////////////////////////////

//별도의 Console창을 이용한 디버깅 수단2

//void main()...

AllocConsole();                                                             // 콘솔창 만든다.

char strBuffer[256]="";

DWORD(또는 size_t) dwWrite;
HANDLE m_hOut = GetStdHandle(STD_OUTPUT_HANDLE);                            // 콘솔창의 핸들 가져옴.
WriteConsole(m_hOut, strBuffer, strlen(strBuffer), &dwWrite, NULL);// 콘솔창에 쓸때
FreeConsole();                                                              // 콘솔창을 없앰.

 

//////////////////////////////////////////////////////////

//별도의 Console창을 이용한 디버깅 수단3

#include <stdio.h>                                                        //또는 #include <iostream>

//void main()...

AllocConsole();

freopen("CONOUT$", "wt", stdout );                       //이것을 사용하면 출력함수 사용이 가능하다

printf("");                                                                        //또는 std::cout << "";

FreeConsole(); 

 

 //////////////////////////////////////////////////////////

 //별도의 Console창을 이용한 디버깅 수단4

//단 WinMainCRTStartup은 컴파일이 되기전에는 생성되지 않으므로 컴파일 후 삽입해주자
 #pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")

#include <stdio.h>                                                          //또는 #include <iostream>

//void main()...

printf("");                                                                         //또는 std::cout << "";

 
쉽고 간단한 방법이라면 1번 방법과 3번 방법이 젤 좋아 보인다.
그중에서 3번이라면 C++ 기초문법 중 하나처럼 별도의 랩핑이나 (기능)클래스 생성 없이
출력창에 간단히 로그를 남길 수 있어 편할 듯 하다.
반응형
Posted by blueasa
, |

유용한 전처리기

Tip & Tech / 2011. 1. 7. 03:13

전처리기.

프리컴파일러(Free가 아니다 : PreCompiler)

 

프로그래머들이 자주 쓰는 전처리기 기능 3가지만 소개하고자 한다.

이것은 쓰라고 강요하기보단 다른 사람(그사람이 현업에서 근무할 가능이 높으므로) 코드를 이해하는데

조금이나마 도움을 주기 때문이다.

 

#pragma comment()

 

ex)

#pragma comment(lib, "dxguid.lib")

 

Project -> Setting -> Link(단축키:ALT+F7)에서 "dxguid.lib"와 "ddraw.lib"와 같은 lib파일을

링크해야 하는 과정을 대신해준다.

 

#pragma warning ()

 

ex)

#pragma warning (disable:4244)

 

4244의 경고 메세지를 출력창에 안보이도록 해준다.

참고로 4244는 무리한(캐스팅연산자가 없이하는) 형변환에 대한 경고이다.

 

#pragma message()

 

ex)

#define _QUOT(x) # x
#define QUOT(x) _QUOT(x)
#define OutputMessage(x)  message( __FILE__ "(" QUOT(__LINE__) ") : " #x )

 

void main()

{

  #pragma OutputMessage(하하하)

}

 

위모양대로 했을경우 컴파일러 출력창에 메세지를 출력해주며 파일과 라인번호를 입력하면

에러났을때 처럼 링크기능이 있다.

cpp의 컴파일 순서를 체크(물론 VC에서는 이에 해당하는 기능도 제공한다)해볼때 유용할거 같다.

[출처] 유용한 전처리기|작성자 나르메

반응형
Posted by blueasa
, |

Gamebryo 셋팅

Gamebryo/Lecture / 2011. 1. 6. 20:45

*게임브리오 설치 전에 VS 2005를 사용시 반드시 서비스팩1를 설치 

(매니패스트 관련 에러가 난다면 버그로 인해 재배포가 안되어서 에러가 나는 것이므로 꼭 패치해야 한다.)

- 추가 라이브러리

NiMesh.lib NiApplication.lib NiSystem.lib NiMain.lib NiInput.lib NiFloodgate.lib NiDx9Renderer.lib NiAnimation.lib

 

*시작

1. Win32API Project로 생성 3DProject로 설정 (빈프로젝트 생성)

2. 클래스 추가->c++클래스 추가 -> base class에 NiApplication등록-> classname은 CGameApplication

3. #include "NiApplication.h" 추가 // 게임브리오 프레임워크

4. 프로젝트 속성 -> 문자집합을 '유니코드' 설정되어 있는것을-> '설정안함'으로 설정

 

 

5. 프로젝트 속성 -> C/C++ -> 64비트 이식성 문제점 검색 -> '아니오' 설정

 

 

6. C/C++ -> 추가포함 디렉터리 -> 자신이 설치한 include폴더로 지정

7. C/C++ -> 전처리기 -> 전처리기 정의 ->WIN32;_DEBUG;_WINDOWS;NIDEBUG;STRICT 추가 

8. 링커 -> 추가라이브러리 디렉터리 -> 자신이 설치한 debuglib폴더로 지정

9. 링커 -> 입력 -> 추가 종속성 -> 위의 추가라이브러리 설정

   NiMesh.lib (메쉬), NiApplication.lib(프레임워크), NiSystem.lib(게임브리오 전반적 시스템), NiFloodgate.lib(Util),

   NiMain.lib(Base), NiInput.lib(input), NiDx9Render.lib(D3D9)

 

10. 도움말 확인

 

 

 이것을 생성한 class에 추가

11. 게임브리오 라이센스를 선언해 주어야 한다.

 #include <NiLicense.h>
NiEmbedGamebryoLicenseCode;

12. 생성한 NiApplication NiApplication::Create()에

     return NiNew CGameApplication; 으로 추가

     NiApplication* NiApplication::Create()
    {
    /*
     new -> NiNew
     delete -> NiDelete
    */
     return NiNew CGameApplication; 
     }

13. 생성한 클래스의 생성자에게 : NiApplication 생성자 추가후

    CGameApplication::CGameApplication(void)
    : NiApplication("Game ver 0.1", DEF_SCREEN_WIDTH, DEF_SCREEN_HEIGHT)

 

* 잠시! 헤더에 대한 설명

NiApplication.h

: public NiMemObject 가 하고 있다. -> 게임브리오가 질접적으로 메모리를 관리하기 위해 사용되고 있는 것

NiRefObject.h

: 참조를 관리해주는 것으로 이것을 상속받고 있는건 참조에 따라 자동삭제를 하기 위해서임(게임브리오에서 쓰는 스마트포인터 같은..)

NiMeshScreenElements.h

: 2D관련해서 작성할 때 추가

NiMesh.h

: 3D관련

 

*슈핑모드 만들기

1. 구성관리자 -> 새로만들기

 

2. 새 솔루션 구성

 

3. 전행처리기

 

4. lib폴더를 shipping으로 추가

 

5. 헤더는 기본헤더로

 

=> shipping모드는 debug 모드보다 더 가볍다.

 

* 직접 초기화 하기(Dx Device Create)

 

 

직접 초기화 하기 위해 CreateRender() 함수를 상속받아와서 아래 코드를 작성한다.

bool CGameApplication:::CreateRenderer()
{
 unsigned int uiWidth = m_pkAppWindow->GetWidth();
 unsigned int uiHeight = m_pkAppWindow->GetHeight();

 m_spRenderer = NiDX9Renderer::Create(uiWidth, uiHeight,
  NiDX9Renderer::USE_NOFLAGS, GetWindowReference(), 
  GetRenderWindowReference());

 if (m_spRenderer == NULL)
 {
  NiMessageBox("Unable to create a renderer!", "Renderer Failure!");
  QuitApplication();
  return false;
 }
 return true;
}

단, #include <NiDX9Render.h>를 추가해야 한다.

이렇게 하면 앞에서 한 예제와 다르게 다이어로그가 뜨면서 어떤 형식으로 실행할 것인지 물어보지 않는다.

왜냐하면 직접 DX로 한다고 선언했기 때문에..

- 다이어로그 뜰때

 

* 중요한 m_spRendere!

DX 디바이스 가져오기

//--직접적으로DirectX를제어하고싶을때

             NiRenderer* renderer = m_spRenderer;

             NiDX9Renderer* pDX9Renderer  = ((NiDX9Renderer*)renderer);

             LPDIRECT3DDEVICE9 pp =pDX9Renderer->GetD3DDevice();

 

-> 스마트 포인터 때문에 NiRenderer* 포인터로 한번 받아온다.


출처 : http://blog.naver.com/fantaldh/40067964992

[출처] Gamebryo 셋팅|작성자 대봉이

반응형

'Gamebryo > Lecture' 카테고리의 다른 글

무기잔상효과  (0) 2011.02.08
캐릭터 기울기 연산  (0) 2011.02.08
게임브리오 강좌(?) 링크  (3) 2010.04.14
Gamebryo 2.5  (0) 2010.04.12
[링크] 게임브리오 강좌  (0) 2010.04.10
Posted by blueasa
, |

VS도움말에도 나와있는 내용이지만 프로젝트가 거대해지면 어쩔 수 없이 헤더파일이 이리저리 엉키고 중복선언하게되는데, 그렇게되면 잘 작동하던 Intellisense가 갑자기 작동하지 않고 상태표시줄에 아래와 같은 메시지가 뜨는 것을 볼 수가 있다.

그림 1 : 에러메시지. (Intellisense가 정상작동하는데도 .또는 ->가 뒤바뀌어서 같은 메시지가 뜨는 경우도 있다. )

 

사실 아래와 같은 Intellisense가 뜨는게 정상인데 말이다.

그림 2 : Intellisense

이럴 땐 VS를 종료하고 프로젝트폴더 안을 보면 프로젝트명.ncb의 파일이 존재하는데 가차없이 삭제해주고 VB를 재실행하면 해결된다.

 

(레퍼런스)----------------------------------------------------------------------

Visual Studio 도움말

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

반응형
Posted by blueasa
, |