printf의 마지막 f formatted(서식화된)를 의미한다.

 

    다양한 종류의 특수 문자

특수 문자

 

\a

경고음 소리 발생

\b

백스페이스(backspace)

\n

개행(한줄띄고 처음으로(캐리지 리턴)하는것을 말한다)

\r

캐리지리턴

\t

수평 탭

\v

수직 탭

\\

백슬래시(\)

\’

작은 따옴표

\”

큰 따옴표

 

서식 문자의 종류와 의미

서식 문자

출력 형태

%c

단일 문자

%d

부호 있는 10진 정수(int)

%s

문자열

%o

부호 없는 8진 정수

%u

부호 없는 10진 정수

%x

부호 없는 16진 정수, 소문자 사용

%X

부호 없는 16진 정수, 대문자 사용

%e

e 표기법에 의한 실수

%E

E 표기법에 의한 실수

%g

값에 따라 %f , %e 둘 중 하나를 선택

%G

값에 따라 %F , %E 둘 중 하나를 선택

%%

% 기호 출력(ex:3% -> %%d)

 

필드 폭

   출력되는 필드의 폭을 지정 할 수 있다.

서식 문자

출력의 형태

%8d

필드 폭을 8칸 확보하고 오른쪽 정렬해서 출력

%-8d

필드 폭을 8칸 확보하고 왼쪽 정렬해서 출력

%+8d

필드 폭을 8칸 확보하고 오른쪽 정렬한 상태에서 양수는 +, 음수는 ?를 붙여서 출력

 

'개발지식창고 > C' 카테고리의 다른 글

C 문자열 함수 정리  (0) 2010.09.20
BASE64 Encode/Decode  (0) 2010.09.20
문자열 처리 함수들  (0) 2010.08.22
32비트 배열을 이용한 상태값 저장 및 얻어오기  (0) 2010.08.16
[C/C++]#define 매크로 팁  (0) 2010.08.16
Posted by 모과이IT
,


[헤더 파일에 선인]
ULONG32 statusDropDownControl; // 동적인 컨트롤 상태를 담기위한 변수 초기화값은 0x00000000
enum
 {
  DROPDOWN_NONE   = 0x00000000, // 0000 0000 0000 0000 0000 0000 0000 0000
  DROPDOWN_COLOR   = 0x00000001, // 0000 0000 0000 0000 0000 0000 0000 0001
  DROPDOWN_SIZE   = 0x00000002, // 0000 0000 0000 0000 0000 0000 0000 0010
  DROPDOWN_FRONT   = 0x00000004, // 0000 0000 0000 0000 0000 0000 0000 0100
  DROPDOWN_FRAMECOLOR  = 0x00000008, // 0000 0000 0000 0000 0000 0000 0000 1000

  DROPDOWN_UPDATE1   = 0x00000010, // 0000 0000 0000 0000 0000 0000 0001 0000
  DROPDOWN_UPDATE2   = 0x00000020, // 0000 0000 0000 0000 0000 0000 0010 0000
  DROPDOWN_UPDATE3   = 0x00000040, // 0000 0000 0000 0000 0000 0000 0100 0000
  DROPDOWN_UPDATE4   = 0x00000080, // 0000 0000 0000 0000 0000 0000 1000 0000
 }; 

[실제 cpp 구현부분]

 * 상대 값들을 추가 할때
 statusDropDownControl |= DROPDOWN_COLOR;
 statusDropDownControl |= DROPDOWN_SIZE;
 statusDropDownControl |= DROPDOWN_FRONT;
 statusDropDownControl |= DROPDOWN_FRAMECOLOR;

* 해당 상태값을 얻을때
if(statusDropDown & DROPDOWN_COLOR)
 {
  ..

  retCount ++;
 }
 
 if(statusDropDown & DROPDOWN_SIZE)
 {
  // Size
  if(SalePriceDlgFormWnd->bb.hStatic[retCount] == NULL)
  ...
  retCount ++;
 }

 if(statusDropDown & DROPDOWN_FRONT)
 {
  // FRONT
  if(SalePriceDlgFormWnd->bb.hStatic[retCount] == NULL)
  ..
  retCount ++;
 }
 
 if(statusDropDown & DROPDOWN_FRAMECOLOR)
 {
  // FRAMECOLOR
  if(SalePriceDlgFormWnd->bb.hStatic[retCount] == NULL)
 ..
  retCount ++;
 }

'개발지식창고 > C' 카테고리의 다른 글

C 문자열 함수 정리  (0) 2010.09.20
BASE64 Encode/Decode  (0) 2010.09.20
문자열 처리 함수들  (0) 2010.08.22
printf 특수문자 출력하기  (0) 2010.08.16
[C/C++]#define 매크로 팁  (0) 2010.08.16
Posted by 모과이IT
,

C/C++ 에서 #define 을 사용을 가급적 자제하도록 권고되고 있지만, 잘 사용할 경우 많은 코딩상의 이득을 볼 수 있습니다.  

#define을 활용하는 예를 몇 가지 설명하려고 합니다.

 

우선 팁을 설명하기 전에 간단하게 ‘##’ “#’ 에 대해 살펴보고 가겠습니다. (샘플소스는 MSDN 에서 가져왔습니다)

 

1.     ‘##’ - Token-Pasting Operator (##): 분리되어 있는 2개의 토큰을 하나로 뭉쳐주는 역할을 합니다.

#define paster( n ) printf( "token" #n " = %d", token##n )


라고 할 때 아래와 같은 코딩은

int token9 = 9;

paster( 9 ); // token##n -> token 과실제인수9 를합쳐token9 가됨


다음과 같이 풀이되어 결국 ‘token9 = 9’ 가 화면에 표시되게 됩니다.

printf( "token" "9" " = %d", token9 );

printf( "token9 = %d", token9 );


이와 같이 ## 은 왼쪽 Operand 와 오른쪽 Operand를 접착제처럼 붙여 주는 역할을 합니다.

 

2.     ‘#’ - Stringizing Operator (#): 매크로 인자를 문자열로 만드는 역할을 합니다.

#define stringer( x ) printf( #x "\n" )


과 같이 정의 할 경우 아래와 같은 문장은

stringer( In quotes in the printf function call\n );


다음과 같이 풀어쓰게 됩니다.

printf( "In quotes in the printf function call\n" "\n" );

 

이제 #define 매크로를 이용한 활용예를 들어 보겠습니다.

1.    배열의 크기 구하기


#define 을 이용하는 가장 간단하고 자주 쓰이는 팁이 아닐까 생각됩니다.

#define arrayCnt( x ) sizeof(x) / sizeof(x[0])


 이를 이용한 간단 샘플입니다.

struct LIST_COL_DEF

{

           int nChar;

           char szText[20];

} ListCol[] =

{

           {20, "폴더"},

           {20, "파일명"}

};

for (int i = 0; i < arrayCnt(ListCol); i++)

{

           // To Do Something...

}

 

물론

i < arrayCnt(ListCol)

를 사용하지 않고

i < sizeof(ListCol) / sizeof(ListCol[0])

을 사용해도 되지만 이와 같은 작업을 여러 번 반복할 경우(array 를 사용하는 경우는 정말 흔하디 흔하죠) 단조로운 코딩이 반복될 수 있어 #define 을 이용한 매크로를 애용하고 있습니다.

 

2.    Get/Set 함수 간단하게 만들기

OOP(Object Oriented Programming)로 프로그램 할 경우 멤버 변수의 Get 함수와 Set 함수를 만들어야 할 경우가 많습니다. 변수를 외부로 드러내지 않고 변수에 대한 접근 Method 만 제공함으로써 추후 변경에 대한 유지보수를 최소화하기 위해 많이 사용하게 되는데요(OOP 의 특징 중에 하나인 Encapsulation). 간단한 Get/Set 함수라 하더라도 하드코딩일 경우 손이 많이 가게 됩니다. 이럴 경우 #define 매크로를 사용하면 단순반복적인 Get/Set 함수를 한 줄만으로 코딩하여 작성할 수 있습니다.


예를 들어 다음과 같은 매크로를 정의한 경우

// SIMPLE_FUNC_IMPL -> Get/Set 함수를자동으로만들어줍니다.

// 1. ret -> return type

// 2. fname -> Get/Set 다음에올함수명

// 3. var -> Get/Set 에대상이되는변수명

#define SIMPLE_FUNC_IMPL(ret, fname, var) \

           ret Get##fname() \

           { \

                     return var; \

           } \

           void Set##fname(ret tmp) \

           { \

                     var = tmp; \

           }

 

bool m_bTest Get 하고 Set 하는 간단한 함수는 아래 한 줄로 만들 수 있게 됩니다.

SIMPLE_FUNC_IMPL(bool, Test, m_bTest);


위 한 줄의 매크로는 자동으로 전 처리기에 의해 컴파일 시 다음과 같은 함수로 확장됩니다.

bool GetTest()

{

           return m_bTest;

}

void SetTest(bool tmp)

{

           m_bTest = tmp;

}


간단하지 않은가요 ^^.

외부로 공개해야 하는 속성이 많으면 많을수록 코딩부담을 줄이고, 미스타이핑으로 인한 오류를 사전에 막아 줄 수 있어 매크로는 더욱 위력을 발휘하게 됩니다.

사실 마이크로소프트의 ATL 3.0 라이브로리 소스 헤더를 분석해 보면 이와 같은 매크로를 훨씬 복잡하게 사용하고 있다는 걸 알 수 있습니다.

아래 샘플은 ATL 3.0 라이브러리 ATLCTL.H 소스에 있는 코드입니다. (소스가 길어 접습니다

 

소스코드 닫기

 

#define IMPLEMENT_STOCKPROP(type, fname, pname, dispid) \

           HRESULT STDMETHODCALLTYPE put_##fname(type pname) \

           { \

                     __if_exists(T::m_##pname) \

                     { \

                                ATLTRACE(ATL::atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \

                                T* pT = (T*) this; \

                                if (pT->m_nFreezeEvents == 0 && pT->FireOnRequestEdit(dispid) == S_FALSE) \

                                          return S_FALSE; \

                                pT->m_##pname = pname; \

                                pT->m_bRequiresSave = TRUE; \

                                if (pT->m_nFreezeEvents == 0) \

                                          pT->FireOnChanged(dispid); \

                                __if_exists(T::On##fname##Changed) \

                                { \

                                          pT->On##fname##Changed(); \

                                } \

                                pT->FireViewChange(); \

                                pT->SendOnDataChange(NULL); \

                     } \

                     return S_OK; \

           } \

           HRESULT STDMETHODCALLTYPE get_##fname(type* p##pname) \

           { \

                     __if_exists(T::m_##pname) \

                     { \

                                ATLTRACE(ATL::atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \

                                ATLASSERT(p##pname != NULL); \

                                if (p##pname == NULL) \

                                          return E_POINTER; \

                                T* pT = (T*) this; \

                                *p##pname = pT->m_##pname; \

                     } \

                     return S_OK; \

           }

소스코드 닫기

 

 끝으로, 이와 같은 #define 매크로의 단점도 잠시 언급하면

-       디버깅이 힘듭니다. 디버깅 시 매크로의 경우 확장된 소스가 보여지지 않아 변수의 변경사항을 추적해 들어 가기가 힘듭니다. 매크로가 복잡할 경우 애로가 있을 수 있어 복잡한 함수의 경우는 위와 같은 방식을 취하지 않는 편이 좋습니다.

-       #define MAX_CUSTOMER 10 보다는
const int MAX_CUSTOMER = 10
으로 코딩 하는 것이 변수가 잘못 typecasting 되는 걸 막을 수 있는 좋은 코딩 습관입니다. 사실 이 부분 때문에 #define 매크로사용을 자제해야 한다고 권장한다고 봐야겠죠.

 

이상으로 #define 매크로에 대해 아주 간단한 팁을 알아봤습니다. 사실 초보자가 아닌 경우 대부분 아실 만한 내용이라 적기가 부끄러운 내용이긴 한데 기록해 둘 경우 나중에 기억이 가물가물해 졌을 때나, 프로그램을 시작하는 다른 분들에게 도움이 될까 하고 적어봤습니다. 오늘도 열코!!

'개발지식창고 > C' 카테고리의 다른 글

C 문자열 함수 정리  (0) 2010.09.20
BASE64 Encode/Decode  (0) 2010.09.20
문자열 처리 함수들  (0) 2010.08.22
printf 특수문자 출력하기  (0) 2010.08.16
32비트 배열을 이용한 상태값 저장 및 얻어오기  (0) 2010.08.16
Posted by 모과이IT
,