#if defined(__WXMSW__)
    #ifdef wxHAVE_RAW_BITMAP
    #include "wx/rawbmp.h"
    #endif
#endif

#if defined(__WXMAC__) || defined(__WXGTK__)
    #define wxHAVE_RAW_BITMAP
    #include "wx/rawbmp.h"
#endif



////Event Table Start
BEGIN_EVENT_TABLE(prjWxEx01Frm,wxFrame)
    ////Manual Code Start
    ////Manual Code End
    
    EVT_PAINT(prjWxEx01Frm::OnPaint)

END_EVENT_TABLE()
////Event Table End


bool MainApp::OnInit()
{
    wxInitAllImageHandlers();
}

void prjWxEx01Frm::drawImage(wxDC* dc)
{
    dc->SetBrush( wxBrush( wxT("orange"), wxSOLID ) );
    dc->SetPen( *wxBLACK_PEN );
    dc->DrawRectangle( 5, 30, 110, 100 );
    
    if(m_bitmap.Ok())
    {
        wxRect rect;
        rect.SetWidth(m_bitmap.GetWidth());
        rect.SetHeight(m_bitmap.GetHeight());

        dc->DrawBitmap(m_bitmap.GetSubBitmap(rect), 10, 35, -1);
    }
}


/*
 * WxBtnNextClick
 */
void prjWxEx01Frm::WxBtnNextClick(wxCommandEvent& event)
{

    //===============
    wxDir wdir(wxGetCwd());

    wxString dir;
    if ( wxFile::Exists(wxT("./Images/crouch.jpg")) ){
        dir = wxT("./Images/");
    }
    else if ( wxFile::Exists(wxT("../../Images/crouch.jpg")) ){
        dir = wxT("../../Images/");
    }

    wxImage image( dir + _T("crouch.jpg" ), wxBITMAP_TYPE_JPEG);
    m_bitmap = wxBitmap( image );
    image.Destroy();


    wxClientDC* clientDC = new wxClientDC(this);
    drawImage(clientDC);
    if (clientDC) delete clientDC;
}


void prjWxEx01Frm::OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc( this );
    PrepareDC( dc );
    
    drawImage(&dc);

}
Posted by stekilove
,
Zdnet 보다가 재미있는 글이 있어서요.

현장에서 마주칠 수 있는 10가지 타입의 프로그래머

Justin James ( TechRepublic )   2008/01/02    
       
 
프로그래머들은 특별한 사람이라고 평가되는 것을 좋아한다. 사실은 어떤 모범
적인 프로그래머들은 다른 프로그래머들의 이상한 점을 개발자들의 커뮤니티 
내에서도 발견한다. 아래에 10가지 타입의 프로그래머를 소개한다. 여러분은 
이 중에 어떤 타입인가?

#1: 간달프(Gandalf)

이 프로그래머 타입은 ‘반지의 제왕’에 나오는 마법사 간달프와 닮았다. 이 
타입의 외관은 턱수염을 기르고, 이상한 모자를 쓰고, 겨울에 망토 같은 외투
를 입을지도 모르며, 좋게 보면 간달프와 같은 마법으로 팀을 위하고, 안 좋
은 면은 팀원들이 간달프가 눈길을 걸어올라 오는 시간을 기다리듯이 그가 전
산실에 오는 시간을 오랫동안 기다려야 한다는 것이다.

이런 타입은 실력이 아주 뛰어난 중요한 인물이지만 보통은 같이 일하기를 꺼
려한다. 하지만 문제가 해결이 안 될 때는 간달프의 마법이 필요하듯 이런 타
입의 도움도 필요한 법이다.

#2: 순교자

다른 업종에서는 순교자(The Martyr)는 워커홀릭이다. 하지만 개발 분야에서 
순교자는 그 차원을 넘어 선다. 워커홀릭은 최소한 집에 가서 샤워하고 잠은 
자기 때문이다. 순교자 타입은 다 먹은 피자 박스에 둘러싸인 책상에 엎드려 
자는 것을 자랑스럽게 생각한다. 

문제는 아무도 이렇게 일하는 것을 원하지 않았다는 것이다. 순교자 타입은 다
른 팀원에게 부담스러운 말을 한다. “먼저들 들어가. 저녁 맛있게 먹고…. 나
는 오늘밤에 3주 동안 해야 할 코딩을 모두 하고 들어갈래.”라는 식으로 말이
다.

#3: 팬보이

팬보이(Fanboy)는 조심해야 한다. 이런 사람이 여러분 주의에 있다면, 그는 드
래곤볼 Z와 건담 윙 중 어느 것이 재미있는지 또는 플레이스테이션3와 X박스 
360중 어느 것이 더 좋은지에 관해 과장 좀 해서 3시간 동안은 이야기를 들어
야 할 것이다. 

팬보이의 책상 주변에는 일본에서 수입한 액션 피규어, 포스터 또는 장식품 등
을 진열해 놓았을 것이다. 이들은 자신들이 가지고 있는 장식품을 가지고 생각
하는 것을 좋아해서, 그 생각에 시간을 많이 허비한다. 이런 타입은 가끔 무
엇 때문에 채용을 했는지 모를 때가 가끔 있다.

#4: 빈스 닐(Vince Neil): 미국 밴드 머틀리 크루의 리드싱어

마치 1984년으로 돌아간 것 같은 타입이다. 긴 머리카락, 찢어진 청바지에 큰 
스카프를 목에 두르고 업무 시간 동안 본 조비, 데프 레퍼드(Def Leppard)와 
같은 음악을 따라 흥얼거리며 일한다. 빈스 타입은 일반적으로 재미있고 경험
도 많지만 발전이 없다. 게다가 힙합 스타일과 아웅다웅할지도 모른다. 이런 
타입과 매일 일하는 것은 꽤 힘들 것이다.

#5: 닌자

닌자 타입은 여러분 팀의 MVP이지만, 아무도 누구인지 모른다는 것이다. 전설
적인 자객처럼, 닌자 타입은 일을 하는 건지 안 하는 건지 모르지만 아침이 되
면 결과물이 나와 있는 것을 발견할 수 있다. 

여러분이 소스 제어 시스템을 가동하고, 새벽 4시에 한번 확인 해보라. 여러분
은 닌자가 그 프로젝트를 알고 있을 것이라고 생각하지도 않았지만, 여러분이 
일주일 동안 작업한 계획의 문제를 코드 레벨에서 확인하고 알려 두었을 것이
다. 여러분이 다른 회의에 참석해 있을 때, 닌자 타입은 일을 하고 있을 테니 
확인해 보라.

닌자 타입은 아주 비밀스럽게 일을 한다. 여러분은 그 사람의 이름조차 모르지
만 모든 프로젝트마다 아주 깔끔하게 정리되어 있는 것을 볼 수 있다. 이런 타
입은 신중하게 다가가야 한다. 이런 사람을 조직 내에서 순위를 매기거나 파일
로 업무를 관리하려고 하지 마라. 닌자 타입은 혼자 일하는 전사이며, 관리 당
하는 것을 싫어한다.

#6: 이론가(The Theoretician)

이 타입은 프로그래밍에 관해 알아야 하는 모든 것을 알고 있다. 이 타입은 애
매한 프로그램 언어의 역사에 관해 4시간 정도 떠드는데 시간을 소비하거나 어
떻게 프로그래밍 하면 런타임을 줄이고, 최적화 프로그래밍을 할 수 있는지에 
대해 시간을 허비할 수 있다. 

문제는 이런 타입은 소프트웨어 개발에 관한 것을 알지 못하고 있다는 것이
다. 이론가 타입이 코딩을 하면 정말 말도 안 되게 ‘엘레강스’하다. 또 좋아
하는 기술은 ‘반복’이며, 모든 코드는 최대한 꼬여 있어 읽는 데 시간이 많
이 걸린다.

이런 타입은 주의가 산만해 쉽게 다른 일에 관심을 돌린다. 몇 시간이면 개발
할 수 있는 일을 이런 타입은 석 달은 족히 걸린다. 왜냐하면 기존의 툴은 충
분하지 않다며 새로운 라이브러리를 만들어 새로운 툴을 만들어 사용하려고 하
기 때문이다. 

이런 타입은 잘만 컨트롤 하면 아주 잘 활용할 수 있다. 프로젝트에서 정확히 
할 일에 대한 범위를 정해 주고 다른 일에 시간을 허비하지 못하게 한다면 말
이다.

#7: 코드 카우보이(The Code Cowboy)

이 타입은 절대 스스로 멈추는 법이 없다. 이런 타입은 거의 항상 최고의 프로
그래머이며, 다른 사람보다 두세배는 빠르게 일을 할 수 있다. 하지만 문제는 
그렇게 빠르게 하는 일의 반을 대충 한다는 것이다. 소스 컨트롤 하는 코드 확
인에 시간이 걸리고, 외부 컨피규레이션 데이터 저장에 시간이 걸리고, 다른 
사람과 대화중에 생각을 이해하는 데도 시간이 걸린다. 

이 타입의 코드는 스파게티처럼 혼란스럽다. 이유는 프로그래밍 하면서 리팩토
링 하는 것이 절대 일어나지 않게 빨리 하기 때문이다. 프로그래밍 책에 예제
로 되어 있는 “이렇게 하지 마세요”라고 7페이지에 걸쳐 중요하게 설명되어 
있는 것과 비슷하게 프로그래밍을 했지만 신기하게도 프로그램은 돌아간다. 

코드 카우보이 타입은 다른 사람과 함께 일을 잘 하지는 못한다. 그리고 여러
분이 이런 타입 두 명을 같은 프로젝트에 투입시키면, 서로의 변화에 대해 인
정을 하지 않고 싸우기 때문에 확실히 실패 한다. 

이 타입은 정확하게 해야 하는 프로젝트보다 납기 일정이 더욱 중요한 프로젝
트에 투입하는 것이 좋고, 코드는 항상 일정 전에 완성되어 있을 것이다. 코
드 카우보이는 ‘시끄러운 닌자 버전’이라고 보면 된다. 닌자가 정교한 외래 
수술을 하는 것에 비유한다면, 코드 카우보이는 성난 소처럼 저돌적으로 자신
의 길을 달려가는 것에 비유할 수 있다.

#8: 공수부대요원(The Paratrooper)

여러분은 영화에서 적지 깊숙이 침투하여 비밀스럽게 업무를 수행하는 특공대 
요원을 본적이 있을 것이다. 이 타입은 소프트웨어 개발 세계에서 ‘공수부대 
요원’이라고 한다. 이 요원은 다 죽어 가는 프로젝트를 살리기 위해 마지막으
로 보내는 프로그래머이다. 

이 요원은 장기 프로젝트에 대해서는 부족하지만, 그들의 최대 자산은 친숙하
지 않는 코드를 배워서 작업을 하는 불가사의한 능력이다. 다른 프로그래머들
은 이러한 것을 충분히 배워서 프로젝트를 실행하는 데 몇 주 내지 몇 달이 걸
릴지도 모르지만, 공수 부대 요원들은 몇 시간 또는 하루 정도면 충분하다. 

이 요원들은 그 코드의 핵심을 알 정도로 배우지는 못하지만, 전체의 팀이 실
패할지도 모르는 곳에서 성공할 수 있는 것을 의미한다.

#9: 보통사람(Mediocre Man)

“충분히 좋다”라고 듣는 것이 이 ‘보통사람’ 타입에게서 들을 수 있는 최
고의 찬사이다. 이 이름에 속지 말아라. ‘보통사람’이라는 타입에는 엄청난 
다양함이 있다. 그리고 이들은 다른 팀원들보다 더 나쁜 코드를 만드는 데 시
간이 더 걸린다. 

이 타입들의 특징은 느리고 침착하게 하지만 프로젝트가 언제 끝날지 모르며, 
회사에 오랫동안 일을 하기 위해 항상 “충분히 좋다”라는 슬로건을 외친다. 

이런 타입을 인터뷰 할 때 그들은 많은 프로젝트에 관여한 사실을 여러분에게 
이야기 하겠지만 실제로 관여한 프로젝트는 많지 않다. 이러한 타입을 알아내
는 것은 쉬운데 그들이 한 일에 대한 자세한 질문을 하면 아마 갑자기 건망증 
증세를 보일 것이다. 이런 타입을 채용한다면 퇴사시키는 데 몇 년은 걸릴 것
이다. 

#10: 이반젤리스트(The Evangelist)

여러분이 어떤 환경에 처해 있더라도, 이반젤리스트는 지금 사용하고 있는 
툴, 프로세스를 버리고 다른 것들로 대체해 업무 향상을 할 수 있다고 주장한
다. 이반젤리스트는 실제로 이론가(The Theoretician)와 정반대이다. 이들은 
솔직하고, 소프트웨어 개발에 관하여 많이 알지만 실질적으로 프로그래밍 작업
은 거의 하지 않는다. 

이들은 자신이 프로젝트 매니저나 부서장이라고 마음속으로 생각하고 있으나 
지식이나 프로젝트 경험은 부족하다. 따라서 이들은 순수하게 경영자 역할을 
할 수 있으므로 다른 사람들은 이들이 변혁을 시도하는 것을 참을 필요가 있
다. @ 

출처 : 
http://www.zdnet.co.kr/news/enterprise/etc/0,39031164,39164694,00.htm
Posted by stekilove
,
http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/gdbm


요즘 사이트에 있어서 mysql, oracle, postgresql 등 RDBMS 가 쓰이지 않는 곳이 거의 없을정도로 많은 인기를 끌고 있다.
그 반면 NIS, BIND, sendmal, LDAP 등 많은 프로그램들이 각각의 자료를 관리하기 위해서 굳이 RDBMS 를 쓰지 않고 ndbm, dbm, gdbm 을 사용하고 있다. 왜 막강한 RDBMS를 쓰지 않고 이러한 간단한 dbm 을 쓰는걸까 ?
그 이유는 간단한 일을 하기 위해서 RDBMS 는 너무 크고 너무 거추장 스럽다는 것이다. 소규모(1000 에서 10000 건) 정도의 전화번호부를 관리한다거나, sendmail 에서 수백건 미만의 hosts(relay 허용등) db를 관리하는데에는 실지로 RDBMS의 기능의 10%도 필요하지 않다. 이러한 간단한 DB를 유지하려고, 서버에 RDBMS 를 설치하고, 운용하고, 프로그래밍을 하고, 복잡한 SQL을 사용하는건 너무 소모적인 일이다. 그래서 이러한 간단한 소규모의 데이타를 관리하기 위해서 dbm 이 존재한다.

dbm 은 관계형 데이타 구조 모델을 가지지 않고, HASH 데이타 구조 모델을 가진다. HASH 는 Key(키), Value(값) 의 한쌍으로 이루어지는 데이타의 집합으로써 키를 이용해서 데이타를 저장하고, 검색하고, 삭제하는 작업을 한다.
어찌 보면 C 에서의 pointer 개념과 비슷하다고 할수 있는데, Value 를 Key 가 가르킨다고 보면 무난할듯 하다.
RDBMS 와는 달리 하나하나의 데이타가 다른 데이타와는 별개로 존재하므로 RDBMS 처럼 데이타간의 관계에 의한 질의 언어가 필요없이 간단하게 Key만을 호출하면, 그 키에 연결된 값을 가져올수 있게된다. 기능의 한계가 명확하므로, 배워서 구현하기가 매우 쉬우며, 작고 또한 빠르다라는 장점을 가진다.

GDBM 은 GNU database mansger 로써 전통적으로 Unix 쪽에서 쓰이던 dbm 의 확장형이다.
아래의 예제는 간단한 주소록이다. 비록 간단하지만 세련된 코드는 아니지만 데이타의 입력, 검색, 삭제 등 dbm 으로써 가져야할 기본적인 기능을 살펴보는데 어려움은 없을것으로 생각된다.

예제 : address.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <gdbm/gdbm.h>

const int FALSE = 0;
const int TRUE = 1;


int main(int argc, char **argv)
{
datum key_data;
datum value_data;
datum return_data;

char cmd_char;
int done = FALSE;

GDBM_FILE dbf;


int block_size = 0;

int temp;

char key_line[80];
char value_line[255];

key_data.dptr = NULL;
value_data.dptr = value_line;

if (access("/tmp/my_dic", F_OK) != 0)
{
printf( "사전 DB 파일이 존재 하지 않습니다"
"영어 사전 DB 파일을 새로 만들겠습니까 (y/n)? ");
cmd_char = getchar();

while(1)
{
if (cmd_char != '')
{
char temp;
do
temp=getchar();
while (temp != '' && temp != EOF);
}

if (cmd_char == EOF) cmd_char = 'n';
switch(cmd_char)
{
case 'y':
dbf = gdbm_open ("/tmp/my_dic", block_size, GDBM_WRCREAT|GDBM_FAST, 00664, NULL);
if (dbf == NULL)
{
perror("db file open error : ");
exit(0);
}
break;
case 'n':
return 1;
break;
}

if (cmd_char == 'y')
break;
}

}
else
{
dbf = gdbm_open ("/tmp/my_dic", block_size, GDBM_READER|GDBM_WRITER, 00664, NULL);
if (dbf == NULL)
{
perror("db file open error : ");
exit(0);
}
}


printf("주소 관리 프로그램입니다. "
"사용법이 궁금하시면 ? 를 입력하세요");
// 사용자의 키보드 입력문자열을 받아서 필요한
// 행동을 취한다.
while(!done)
{
printf("com -> ");
cmd_char = getchar();

if (cmd_char != '')
{
char temp;
do
temp = getchar();
while (temp != '' && temp != EOF);
}
if (cmd_char == EOF) cmd_char = 'q';

switch (cmd_char)
{
case 'q':
done = TRUE;
break;
case '?':
printf("i -- insert data"
"f -- fetch data"
"c -- data num"
"d -- data delete"
"q -- quit");
break;

case '':
printf("");
break;
case 'i':
if (key_data.dptr != NULL) free(key_data.dptr);
printf("Key -> ");
fgets (key_line, 80, stdin);
key_line[strlen(key_line) - 1] = '0';

key_data.dptr = key_line;
key_data.dsize = strlen(key_line) + 1;

printf("Value -> ");
fgets(value_line, 255, stdin);

value_data.dsize = strlen(value_line) + 1;
if (gdbm_store (dbf, key_data, value_data, GDBM_REPLACE) != 0)
printf("Item no inserted ");
printf("");
key_data.dptr = NULL;
break;

case 'f':
if (key_data.dptr != NULL) free(key_data.dptr);
printf("Key -> ");
fgets (key_line, 80, stdin);
key_line[strlen(key_line) -1] = 0;
key_data.dptr = key_line;
key_data.dsize = strlen(key_line) + 1;

return_data = gdbm_fetch(dbf, key_data);
if (return_data.dptr != NULL)
{
printf("data -> %s", return_data.dptr);
free(return_data.dptr);
}

else
printf("No Such item found. ");
key_data.dptr = NULL;
break;
case 'c':
temp = 0;

if (key_data.dptr != NULL) free (key_data.dptr);
return_data = gdbm_firstkey(dbf);
while(return_data.dptr != NULL)
{
temp ++;
key_data = return_data;
return_data = gdbm_nextkey(dbf, key_data);
free(key_data.dptr);
}
printf("%d 개의 자료가 있습니다", temp);
key_data.dptr = NULL;
break;

case 'a':
key_data = gdbm_firstkey(dbf);
if (key_data.dptr == NULL)
{
printf("No one tiem found");
break;
}
else
{
printf("%s => ", key_data.dptr);
return_data = gdbm_fetch(dbf, key_data);
printf("%s", return_data.dptr);
free(return_data.dptr);
}
while(1)
{
return_data = gdbm_nextkey(dbf, key_data);
if (return_data.dptr != NULL)
{
free(key_data.dptr);
key_data = return_data;
printf("%s => ", key_data.dptr);
return_data = gdbm_fetch(dbf, key_data);
printf("%s", return_data.dptr);
free(return_data.dptr);
}
else
{
printf("No such item found.");
break;
}
}
key_data.dptr = NULL;
break;

case 'd':
if (key_data.dptr != NULL) free (key_data.dptr);

printf("Key -> ");
fgets (key_line, 80, stdin);
key_line[strlen(key_line) -1] = 0;
key_data.dptr = key_line;
key_data.dsize = strlen(key_line) + 1;
if(gdbm_delete (dbf, key_data) != 0)
printf("Item not found or deleted");
key_data.dptr = NULL;
break;
}
}

printf("bye bye");
return 0;
}

datum 의 dptr 멤버는 malloc 를 이용해서 메모리를 할당하고, 자동으로 해제시켜주지 않는다. 그러므로 반드시 필요없다고 생각되는 곳에서 free 를 해줘야 메모리 누수 및 오류를 방지할수 있다.
위 코드는 매우 명확해 보이므로 별도로 설명을하진 않을 생각이다. 아리송하더라도 한번 정도 컴파일 해서 사용해보면서 코드를 보면 쉽게 이해가 될것이다.
gdbm 에 대한 자세한 내용은 man 페이지를 참고하라
컴파일 방법은 아래와 같다. [yundream@localhost test]# gcc -o address address.c -lgdbm
Posted by stekilove
,