Skip to main content

Posts

Showing posts from October, 2006

Google Image Labeler

언제부터 있었는지 모르겠는데 Google Image Labeler 라는 서비스가 있네요. 일종의 게임입니다. 둘이 짝을 이뤄 해당하는 그림의 label을 붙이는 것이죠. 이때 둘이 같은 label을 붙이면 점수가 올라가는 방식입니다. 아무 생각 없이 시작했다는데 한 30분은 후딱 가는군요. ;-) 자기 회사의 이미지 검색의 질도 높이면서 재미도 제공하고... 아이디어가 멋집니다. 예전에 Google에서 PigeonRank 라는 기술을 공개했었는데 왠지 제가 그 비둘기들의 자리를 차지하고 앉은 것 같더군요. :-) 참고로 어제 새로 설치한 Firefox 2.0은 정말 좋군요~ Firefox 설치한 김에 IE7도 설치했는데 뭐가 문제인지 자꾸 죽어서 IE7은 결국 uninstall 했습니다. :-| (요새 xml 라이브러리를 만드느라 C++ 관련 글이 좀 뜸합니다. 이제 작업이 거의 중반에 접어들어가는데요 앞으로 xml 라이브러리 만들면서 사용한 방법이나 새로 배운 내용에 대해 하나씩 소개하도록 하겠습니다.)

emacs + cvs

CVS vs SVN 글을 보고 갑자기 emacs에서 cvs사용법이 궁금해졌습니다. 회사에선 version control system으로 clearcase를 사용하고 있고 cvs는 open source project들의 소스 코드를 다운받을 때나 sf.net에 만든 프로젝트 작업시에만 조금 사용해 본 정도입니다. sf.net에서 사용할 때는 주로 eclipse의 plug-in을 사용했죠. :-) (sf.net에서도 svn을 지원합니다.) 가끔 이 홈페이지에 글을 올릴때 사용했던 코드들을 나중에 찾아보면 지워져 있어서 개인 linux machine에서도 cvs를 사용해 볼까 생각해 왔었는데 이번 기회에 시작하게 되었네요. 물론 shell에서 cvs 명령어들을 외워서 입력하는 것은 어려울 것 같아 emacs에서 사용하는 방법에 대해 알아보았습니다. Creating a repository 먼저 cvs repository를 만들어야 하는데 다음과 같이 간단하더군요. 제 경우엔 혼자 사용할 용도라 $HOME 밑에 만들었습니다. mkdir $HOME/cvsroot cvs -d $HOME/cvsroot/ init export CVSROOT=$HOME/cvsroot/ 마지막 줄의 export는 앞으로 설명할 cvs 명령어에서 '-d $HOME/cvsroot' 인자를 생략하도록 해줍니다. 하지만 일단 파일들이 cvs 관리하에 들어가면 파일들의 CVSROOT가 어딘지 저장하고 있기 때문에 이런 export는 필요 없습니다. Creating a directory tree from a number of files 제 경우엔 현재 작업중인 xmlcpp 관련 소스 코드들을 cvs로 관리하기로 하였습니다. 다음과 같은 명령어를 사용하여 CVSROOT에 xmlcpp라는 디렉토리를 생성합니다. cd works/xmlcpp cvs import -m "import source code" xmlcpp ideathinking start 여기서 __ideathinki

양자인간

[bookcover:8988349059] ((원래 읽었던 책은 더 오래된 것이라 더이상 이미지를 구할 수가 없네요.)) 제목이 좀 유치하지만 이백살을 맞은 사나이 라는 중편을 다시 장편으로 만든 작품의 제목입니다. 로빈 윌리엄스 주연의 영화 바이센테니얼맨 (Bicentennial Man) 의 원작이지요. 영화를 보지는 못했지만 꼭 한번 보고 싶어지는군요. 아시모프의 작품입니다. 내용은 양자 두뇌 개발 초기의 로봇 NDR-113시리즈 중의 하나인 앤드류 마틴이 인간처럼 생각할 수 있게 되면서 벌어지는 일들입니다. 앤드류가 가장 원하는 것은 바로 인간이 되는 것이죠. 이를 이루어가는 과정이 차분히 전개됩니다. 마지막 부분에선 눈시울도 붉어지더라는... ㅜㅜ 제가 어렸을때만 해도 미래 하면 생각나는 것들은 우주 여행, 로봇, 인공 지능같은 것들이었습니다. 하지만 수십년이 지난 지금도 그때에 비해 이 분야들은 별로 눈에 띄는 발전이 없었던 것 같습니다. 왠지 인터넷이나 바이오, 나노, 유전 공학같은 것들이 뜻밖의 발전을 하면서 사람들의 관심이 전부 지구 내적인 것으로 바뀐것 같다고나 할까요? 왠지 어려서 꿈꾸었던 미래의 이미지들보다는 낭만적이지 못하네요. 언젠가 다시 본격적인 우주 개발이 시작되서 제가 우주 여행을 해보고 죽어야 할텐데요... :-| 암튼 올해 는 예전에 나왔던, 하지만 읽어 보지 못했던 명작들을 찾아서 읽고 있는데 칼 세이건의 콘택트 와 더불어 별 다섯개짜리입니다. 강추! :-)

char 타입과 EOF

요새 한참 XML parser를 만들기 위해 이것 저것 공부도 하고 코딩도 하고 있는 중입니다. 그런데 역시 아는 것과 하는 것 사이에는 많은 차이가 있군요. Devils in the details랄까요? ;-) 이번 글에서는 char 타입과 EOF에 관한 내용에 대해 생각해 볼까 합니다. 다들 아시다시피 기존의 8bits char 타입을 사용하는 C 함수들의 경우 char를 리턴하기 위해 int 타입을 사용하였습니다. ex) int fgetc(FILE *stream); 이유는 하나, 실제 사용되는 char 값들과 EOF값을 구분하기 위해서였죠. 8bits char 타입의 값들은 char가 unsigned라고 가정하면 ((char나 wchar_t의 signed, unsigned 여부는 구현에 따라 다를 수 있습니다.)) 0~255까지의 범위안의 값들만 가질 수 있기 때문에 256부터의 값은 어떤 것이든 EOF를 나타내기 위해 사용될 수 있습니다. 일반적으로 -1, 즉 0xFFFFFFFF이 사용되죠. 그런데 이번에 XML parser를 구현하면서 평소에 잘 사용하지 않던 wchar_t 타입을 사용하다 보니 궁금한 점이 생겼습니다. Linux의 g++에서 wchar_t의 sizeof는 32bits입니다. 그렇다면 WEOF의 타입은 무엇이어야 할까요? 또 값은요. 만약 wchar_t의 값이 0~0xFFFFFFFF을 모두 사용할 수 있다고 생각한다면 ((wchar_t가 unsigned라고 가정했을 경우)) WEOF의 타입은 uint64_t 정도가 되어야 할 것입니다. 하지만 64bits int 타입을 아직 모든 컴파일러가 지원하는 것은 아니므로 문제가 될 수 있습니다. 그래서 아래와 같이 간단한 코드를 사용하여 시험해 보았습니다. cout << sizeof(char) << ", " << sizeof(EOF) << ", " << EOF << endl; cout <&

emacs에서 Bitstream Vera Sans Mono 폰트 사용하기

대부분의 코딩 작업은 emacs를 사용하지만 잠깐 코드를 살펴볼 필요가 있거나 환경이 여의치 않을때는 터미널에서 vi를 사용하곤 합니다. Ubuntu에서는 터미널의 기본 폰트가 Bitstream Vera Sans Mono 라는 폰트인데 이 폰트로 코드를 보면 왠지 더 코드가 좋아 보이더군요. -_-; (이거 설치한다고 반나절을 보냈더니 이 긴 폰트 이름이 외워지는군요. :-) ) 그래서 찾아보니 emacs에서도 이런 anti-aliasing 폰트를 사용하는 방법이 있더군요. 그럼 제가 사용한 방법을 소개하겠습니다. ((참고한 사이트는 여기 였는데 여기 에 한글로 된 소개도 있더군요.)) 사용한 OS는 Ubuntu 6.06입니다. 먼저 Synaptic Pakage Manager를 사용하여 다음 패키지들이 설치되어 있는지 확인합니다. libgtk2.0-dev emacs-snapshot 이 패키지들이 없으면 make시에 에러가 발생하더군요. 아래와 같이 소스 코드를 가져옵니다. XFT_JHD_BRANCH는 개발이 중단된 branch라고 emacs-unicode2나 unicode-xft branch를 사용하라는 글들이 많았은데 이 두 버전은 아직 폰트 관련 버그가 있어 보입니다. cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co -rXFT_JHD_BRANCH emacs 다음과 같이 build합니다. 아직 이 branch가 정식 release된 것이 아니라 바로 /usr 밑에 인스톨하긴 껄끄러워서 $HOME에 인스톨했습니다. 회사에서 사용하는 Linux 서버에는 당연하게도 root 계정이 없다보니 필요한 프로그램을 $HOME에 설치하는게 저에겐 자연스럽네요. ;-) configure --prefix=$HOME --with-gtk --with-xft --x-includes=/usr/include/X11 --x-libraries=/usr/lib/X11 make bootstrap make mak

C++ of the Day #35 - k-permutation, k-combination

C++의 algorithm 라이브러리에는 N!개의 permutation을 구할 수 있는 next_permutation과 prev_permutation 함수가 존재합니다. 하지만 N개의 element들중에 k개를 구하는 k-permutation에 대한 함수는 제공하지 않죠. 이번 글에서는 k-permutation을 위한 함수를 만들어 보겠습니다. 먼저 permutation의 예를 들어 보면 다음과 같습니다. { 1, 2, 3 }과 같이 3개의 element를 가지고 next_permutation을 하면 다음과 같이 3!개의 permutation이 만들어집니다. 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 다음으로 { 1, 2, 3, 4 } 4개를 element에서 2개를 고르는 k-permutation의 경우에는 다음과 4! / (4 - 2)!개의 permutation이 만들어집니다. 1 2 1 3 1 4 2 1 2 3 2 4 3 1 3 2 3 4 4 1 4 2 4 3 마지막으로 { 1, 2, 3, 4 }의 4개를 가지고 2개를 순서에 상관 없이 고르는 k-combination의 경우에는 다음과 4! / (2! * (4 - 2)!)개의 combination이 만들어집니다. 1 2 1 3 1 4 2 3 2 4 3 4 그럼 이제 k-permutation을 위한 next_k_permutation 함수에 대해 먼저 살펴 보겠습니다. 만약 4개의 element를 가지고 next_permutation을 한다면 다음과 같은 결과가 나올 것입니다. 1 2 3 4 << 1 2 4 3 1 3 2 4 << 1 3 4 2 1 4 2 3 << 1 4 3 2 2 1 3 4 << ... 위에서 두개만 고르는 k-permutation은 << 표시가 된 라인만 리턴하도록 구현되어야 합니다. 따라서 N개에서 k개를 고르는 k-permutation을 구현하기 위해서는 입력된 구간의 [first + k, last) 영역을 역

Unicode와 Encoding에 대해 몰랐던 사실들

요새 XML parser를 만들어 본다고 encoding에 대해 좀 살펴보고 있는데 제가 그동안 알아왔던 것들과 많이 차이가 나네요. 사실 그동안 십수년 프로그래밍을 하면서 I18n이나 L10n을 고려해 본적은 없었거든요. ((Internationalization (I18n), Localization (L10n) )) 대부분 UI가 없거나 UI가 있더라도 그다지 한글화같은 것을 고려하지 않았도 되었던 것이기도 했고요. 가장 오해하고 있었던 사실은 Unicode는 16bit 크기안에 다 들어갈 수 있다라고 알고 있던 것이었습니다. 그런데 살펴 보니 이것은 옛날 얘기고 현재는 plane-0에만 해당하는 범위네요. 이외에도 plane-1부터 plane-16까지 가질 수 있더군요. 물론 대부분의 현재 사용되는 문자들은 16bit안, 즉 plane-0에 들어간다고 하지만 제대로 Unicode를 fixed length string으로 지원하려고 하면 16bit char로는 불가능하다는 말이 되죠. 시험삼아 간단히 컴파일을 해보니 Windows XP에서 사용한 VC++ 2005 Express에서는 wchar_t가 16bit지만 Ubuntu의 gcc에서는 32bit네요. 원래 계획은 XML parser를 만들면서 기본적으로 wchar_t로 결과를 리턴하고 encoding이 ascii (utf-8의 subset) 인 경우 char로 결과를 리턴하도록 template class로 만들려고 했었는데 wchar_t가 16bit인 환경에서는 어째야 할지 고민이네요. 어차피 현재 사용되는 대부분의 문자들이 16bit안에 들어가므로 plane-0만 지원해도 될것 같기도 한데... 아니면 basic_string 대신 basic_string 를 사용하는 방법을 사용해야 할런지... 이렇게 하려면 저장될때 byte ordering도 고려해야 하고 수많은 traits이나 function overloading을 새로 만들어 주어야 하겠죠. string literal 쓰기도 어렵겠네요. :-|

C++ of the Day #34 - dynamic visitor 2

이번 글에서는 지난번 글 에서 살펴보았던 dynamic visitor를 개선해 보도록 하겠습니다. 먼저 이전 구현에서 불편한 점을 알아보겠습니다. struct B {} struct D1 : B {} struct D2 : B {} void print(D1* ) { cout << "D1n"; } void print(D2* ) { cout << "D2n"; } 이전과 같은 B, D1, D2 클래스가 있습니다. 달라진 점은 print라는 함수가 D1과 D2 클래스에 대해 이미 존재한다는 점입니다. 이 클래스들을 가지고 dynamic_visitor를 사용하면 다음과 같습니다. typedef mpl::vector TL; struct PrintVisitor : dynamic_visitor { void visit(B* b) { cout << “Bn”; } void visit(D1* b) { cout << “D1n”; } void visit(D2* b) { cout << “D2n”; } }; 여기서 문제는 이미 D1, D2에 대해 print라는 함수가 구현되어 있는데 PrintVisitor에서 다시 구현해야 한다는 점입니다. 물론 이 예제에서는 코드가 짧아 별 문제 없어 보이지만 긴 코드라면 문제가 됩니다. DRY 규칙에 어긋나는 것이죠. ((Don't Repeat Yourself.)) 그럼 이번 글에서 살펴볼 개선된 dynamic_visitor의 사용법을 보겠습니다. typedef mpl::vector TL; struct PrintVisitor : dynamic_visitor { PrintVisitor() { assign_impl (print); assign_impl (print); } void visit(B* b) { cout << “Bn”; } }; 만약 base 클래스인 B 클래스에 대한 visit함수가 아무 일도 안해도

The C++ Standard Library Extensions: A Tutorial and Reference

[bookcover:0321412990] 이제 막 The C++ Standard Library Extensions: A Tutorial and Reference 을 다 읽었습니다. 중간에 math library와 C99 compatibility 부분에서 속도가 늦어져 조금 오래 걸렸네요. ;-) 책은 tr1에 대한 완전한 내용을 담고 있습니다. 이 중 대부분은 boost 문서를 통해 어느 정도 알던 것이었지만 random number generator나 regular expression 라이브러리등의 자세한 사용법은 이 책을 통해 알게 되었네요. 책은 tr1에 대한 내용을 간단한 예제들과 함께 소개하고 있는데 거의 reference manual 형식입니다. 아쉬운 점은 예제의 출력 내용이 없어 실제 예제의 출력이 정확히 무엇인지 볼 수 없다는 점이었습니다. 물론 예제는 다운로드 받을 수 있으나 컴파일하려면 tr1 라이브러리와 지원 컴파일러가 있어야 하겠죠? ((Dimkumware Ltd.의 Dinkum TR1 라이브러리 와 MSVC 7.1, gcc 3.4.3 컴파일러를 사용하여 테스트했다고 합니다. 물론 boost 라이브러리를 사용하면 대부분의 내용이 사용 가능합니다.)) 대부분의 초판인 책들에서 발견되는 오기들을 이 책에서는 거의 찾을 수 없었구요. tr1 라이브러리의 내용이 정확히 어떤 내용인지 알고 싶으신 분들은 한번 읽어두시면 좋겠네요. 책을 읽고 나니 boost 라이브러리에는 있으나 tr1에는 없는 라이브러리들이 생각보다 너무 많다는 생각이 들었습니다. 만약 tuple과 mpl을 하나의 코드에서 사용하고 싶다면 tr1::tuple과 boost::mpl을 사용하는 것이 좋을지 그냥 boost 라이브러리만 사용하는 것이 좋을지 모르겠네요. 아마 제 경우엔 그냥 boost 라이브러리만 사용하게 될 것 같습니다. 또하나... boost에서 얼른 unordered_set과 unordered_map을 지원해 주었으면 좋겠습니다. 이것 하나때문에 STLport같

C++ of the Day #33 - dynamic visitor

까막님의 downcast_overloader 코드 를 보고 이런 코드가 어떤 경우에 쓸모가 있을까 생각하다가 만들어 본 내용입니다. 먼저 다음과 같이 클래스들이 있다고 가정합니다. struct B {} struct D1 : B {} struct D2 : B {} 이 클래스들에 polymorphic하게 자기 클래스의 이름을 print하는 기능을 추가하는 방법에 대해 살펴보겠습니다. 먼저 위 클래스들이 있는 코드를 자유롭게 수정할 수 있다면 다음과 같이 virtual 함수를 추가하면 됩니다. struct B { virtual void print() const { cout << "Bn"; } }; struct D1 : B { void print() const { cout << "D1n"; } }; struct D2 : B { void print() const { cout << "D2n"; } }; 위 함수를 사용하는 방법은 다음과 같습니다. B* b1 = new D1; B* b2 = new D2; b1->print(); b2->print(); 너무 간단하죠? :-) 그럼 다음으로 이 클래스들이 있는 소스 코드를 수정할 수 없는 경우를 알아보겠습니다. 이런 경우에는 라이브러리 설계자들이 자신이 만든 클래스의 코드 수정 없이 사용자에 의한 확장이 가능하도록 하기 위해 Visitor 패턴을 지원할 가능성이 높습니다. 이 경우 B, D1, D2 클래스는 다음과 같이 되어 있을 것입니다. struct Visitor { virtual void visit(B* b) {} virtual void visit(D1* b) {} virtual void visit(D2* b) {} }; struct B { virtual void accept(Visitor* v) { v->visit(this); } }; struct D1 : B { void accept(Vis