Friday, December 25, 2009

Word Index ( 2009 )

This problem is from ProgFest Contest 2009( 02/14/2009 ). During the contest, I got stuck on this problem for 2 hours, really really dumb when I thought over it. It is probably one of the easiest problems that I have missed T_T !

Problem :

Consider the English alphabet {a,b,c,...z}. Using this alphabet, a set of valid words is to be formed that are in a strict lexicographic order. In this set of valid words, the successive letters of a word are in a strictly ascending order; that is, later letters in a valid word are always after previous letters with respect to their positions in the alphabet list {a,b,c...,z}. For example,
abc aep gwz
are all valid three-letter words, whereas
aab are cat
are not.

For each valid word associate an integer which gives the position of the word in the alphabetized list of words. That is:
a --> 1
b --> 2
.
.
z --> 26
ab --> 27
ac --> 28
.
.
az --> 51
bc --> 52
.
.
vwxyz --> 83681
Your program is to read a series of input lines. Each input line will have a single word on it, that will be from one to five letters long. For each word read, if the word is invalid give the number 0. If the word read is valid, give the word's position index in the above alphabetical list.
Input
The input consists of a series of single words, one per line. The words are at least one letter long and no more that five letters. Only the lower case alphabetic {a,b,...,z} characters will be used as input. The first letter of a word will appear as the first character on an input line.
The input will be terminated by end-of-file.
Output
The output is a single integer, greater than or equal to zero (0) and less than or equal 83681. The first digit of an output value should be the first character on a line. Note: This may not be a default-format. There is one line of output for each input line.

Sample Input
z
a
cat
vwxyz

Sample Output

26
1
0
83681

Solution :

#include <string>
#include <iostream>
#include <sstream>
#include <map>

using namespace std;

bool is_valid( const string& s ) {
for( int i = 1; i < s.length(); ++i ) {
if( s[ i ] <= s[ i - 1 ] )
return false;
}
return true;
}

map< string, int > generate() {
char previous_char;
int index = 1;
map< string, int > m;

int count = 0;
for( char i1 = 'a'; i1 <= 'z'; ++i1 ) {
count++;
ostringstream o;
o << i1;
m.insert( pair< string, int >( o.str(), count ) );
}

for( char i1 = 'a'; i1 <= 'z'; ++i1 ) {
for( char i2 = i1 + 1; i2 <= 'z'; ++i2 ) {
count++;
ostringstream o;
o << i1 << i2;
m.insert( pair< string, int >( o.str(), count ) );

}
}

for( char i1 = 'a'; i1 <= 'z'; ++i1 ) {
for( char i2 = i1 + 1; i2 <= 'z'; ++i2 ) {
for( char i3 = i2 + 1; i3 <= 'z'; ++i3 ) {
count++;
ostringstream o;
o << i1 << i2 << i3;
m.insert( pair< string, int >( o.str(), count ) );
}
}
}

for( char i1 = 'a'; i1 <= 'z'; ++i1 ) {
for( char i2 = i1 + 1; i2 <= 'z'; ++i2 ) {
for( char i3 = i2 + 1; i3 <= 'z'; ++i3 ) {
for( char i4 = i3 + 1; i4 <= 'z'; ++i4 ) {
count++;
ostringstream o;
o << i1 << i2 << i3 << i4;
m.insert( pair< string, int >( o.str(), count ) );
}
}
}
}

for( char i1 = 'a'; i1 <= 'z'; ++i1 ) {
for( char i2 = i1 + 1; i2 <= 'z'; ++i2 ) {
for( char i3 = i2 + 1; i3 <= 'z'; ++i3 ) {
for( char i4 = i3 + 1; i4 <= 'z'; ++i4 ) {
for( char i5 = i4 + 1; i5 <= 'z'; ++i5 ) {
count++;
ostringstream o;
o << i1 << i2 << i3 << i4 << i5;
m.insert( pair< string, int >( o.str(), count ) );
}
}
}
}
}

return m;
}

int main() {
map< string, int > m = generate();
string input;
while( cin >> input ) {
if( is_valid( input ) == false )
cout << "0" << endl;
else
cout << m[ input ] << endl;
}
return 0;
}


Thursday, September 24, 2009

Credit Card Processing

Credit Card Processing from Problem Set 2005-2006

http://www.socalcontest.org/current/index.shtml

Solution :

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cctype>
#include <sstream>
#include <vector>

using namespace std;

string util_trim_right( const string& s, const string& delim = " " ) {
string temp( s );
string::size_type o = temp.find_last_not_of( delim );
if ( o == string::npos )
return temp;
else
return temp.erase( temp.find_last_not_of( delim ) + 1 );
}

string util_trim_left( const string& s, const string& delim = " " ) {
string temp( s );
return temp.erase( 0, s.find_first_not_of( delim ) );
}

vector< string > util_tokenize_string( const string& str, const string& del = "," ) {
vector< string > result;
string::size_type start = 0;
string::size_type end = str.find_first_of( del, start );
string::size_type length = str.length();
string word;

while ( string::npos != end && end < length ) {
word = str.substr( start, end - start );
result.push_back( word );
start = end + 1;
end = str.find_first_of( del, start );
}

end = str.find_last_of( del ) + 1;
result.push_back( str.substr( end ) );

return result;
}

void util_delete_all_white_space( string& s ) {
s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
}

bool util_is_all_white_space( const string& s ) {
for ( unsigned o = 0, o_end = s.length(); o < o_end; ++o )
if ( s[ o ] != ' ' )
return false;

return true;
}


class Customer {
public :
string cu_first_name;
string cu_last_name;
string cu_address;
string cu_city;
string cu_state;
string cu_zipcode;
string cu_ssn;
string cu_credit_1;
string cu_credit_2;
string cu_credit_3;
char cu_literal_semicolon;

public :
// bussiness rule 1
bool cu_test_leading_white_space_and_null() const;

// bussiness rule 2
bool cu_test_byte_field_isdigit_isalpha() const;

// bussiness rule 3
bool cu_test_credit_score() const;

// bussiness rule 4
bool cu_test_credit_score_mean() const;

void cu_show_customer_info() const;

};


void Customer::cu_show_customer_info() const {
cout << "1." << cu_first_name << "\n";
cout << "2." << cu_last_name << "\n";
cout << "3." << cu_address << "\n";
cout << "4." << cu_city << "\n";
cout << "5." << cu_state << "\n";
cout << "6." << cu_zipcode << "\n";
cout << "7." << cu_ssn << "\n";
cout << "8." << cu_credit_1 << "\n";
cout << "9." << cu_credit_2 << "\n";
cout << "10." << cu_credit_3 << "\n";
}

bool Customer::cu_test_credit_score() const {
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

if (
val_1 < 400 ||
val_2 < 400 ||
val_3 < 400 ) {

return false;
}

return true;
}

bool Customer::cu_test_credit_score_mean() const {
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

double mean = static_cast< double >( val_1 + val_2 + val_3 ) / 3.0;
if ( mean < 500 ) {
return false;
}

return true;
}

bool Customer::cu_test_byte_field_isdigit_isalpha() const {

// check literal_semicolon
if ( cu_literal_semicolon != ';' )
return false;

// check byte field
if ( cu_state.length() != 2 || cu_zipcode.length() != 5 )
return false;

// check city for non-alphanumeric
for ( unsigned o = 0, o_end = cu_city.length(); o < o_end; ++o ) {
if ( isdigit( cu_city[ o ] ) == false && isalpha( cu_city[ o ] ) == false )
return false;
}

// check state for only alphabetic
for ( unsigned o = 0, o_end = cu_state.length(); o < o_end; ++o ) {
if ( isalpha( cu_state[ o ] ) == false )
return false;
}

// check zipcode for only numeric
for ( unsigned o = 0, o_end = cu_zipcode.length(); o < o_end; ++o ) {
if ( isdigit( cu_zipcode[ o ] ) == false )
return false;
}

// check ssn for only numeric
for ( unsigned o = 0, o_end = cu_ssn.length(); o < o_end; ++o ) {
if ( isdigit( cu_ssn[ o ] ) == false )
return false;
}

unsigned CREDIT_DIGITS = 3;
// check credit_1, credit_2, credit_3 for only numeric
for ( unsigned o = 0; o < CREDIT_DIGITS; ++o ) {
if (
isdigit( cu_credit_1[ o ] ) == false ||
isdigit( cu_credit_2[ o ] ) == false ||
isdigit( cu_credit_3[ o ] ) == false ) {

return false;
}
}

// check credit_1, credit_2, credit_3 for valid range ( 200 - 800 )
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

if (
val_1 < 200 || val_1 > 800 ||
val_2 < 200 || val_2 > 800 ||
val_3 < 200 || val_3 > 800 ) {
return false;
}

return true;
}

bool Customer::cu_test_leading_white_space_and_null() const {

// check for NULL character
if ( cu_literal_semicolon == ' ' )
return false;

// check for NULL string

if (
util_is_all_white_space( cu_first_name ) == true ||
util_is_all_white_space( cu_last_name ) == true ||
util_is_all_white_space( cu_address ) == true ||
util_is_all_white_space( cu_city ) == true ||
util_is_all_white_space( cu_state ) == true ||
util_is_all_white_space( cu_zipcode ) == true ||
util_is_all_white_space( cu_ssn ) == true ||
util_is_all_white_space( cu_credit_1 ) == true ||
util_is_all_white_space( cu_credit_2 ) == true ||
util_is_all_white_space( cu_credit_3 ) == true ) {

return false;
}

// check for leading white space
if (
cu_first_name[ 0 ] == ' ' ||
cu_last_name[ 0 ] == ' ' ||
cu_address[ 0 ] == ' ' ||
cu_city[ 0 ] == ' ' ||
cu_state[ 0 ] == ' ' ||
cu_zipcode[ 0 ] == ' ' ) {

return false;
}

return true;
}

vector< Customer > main_prog_get_data_from_file( const char* file_name ) {
ifstream o( file_name );
string oneline;
vector< Customer > cus_vec;

while ( getline( o, oneline ) ) {

cout << oneline << endl;
Customer cus;
string temp; // use for a_c_s_z string

// get the last character
cus.cu_literal_semicolon = oneline[ 89 ];

for ( unsigned o = 0; o < 12; ++o ) {
cus.cu_first_name.push_back( oneline[ o ] );
}

for ( unsigned o = 12; o < 29; ++o ) {
cus.cu_last_name.push_back( oneline[ o ] );
}

for ( unsigned o = 30; o < 71; ++o ) {
temp.push_back( oneline[ o ] );
}

for ( unsigned o = 71; o < 79; ++o ) {
cus.cu_ssn.push_back( oneline[ o ] );
}

for ( unsigned o = 80; o < 83; ++o ) {
cus.cu_credit_1.push_back( oneline[ o ] );
}

for ( unsigned o = 83; o < 86; ++o ) {
cus.cu_credit_2.push_back( oneline[ o ] );
}

for ( unsigned o = 86; o < 89; ++o ) {
cus.cu_credit_3.push_back( oneline[ o ] );
}


/* trim right for :
1. first name
2. last name
*/
cus.cu_first_name = util_trim_right( cus.cu_first_name );
cus.cu_last_name = util_trim_right( cus.cu_last_name );

/*
Since we need to have enough commas( 3 )
to handle the tokenizer, we need to test :
1. All whitespace
2. No comma
3. Not enough comma

One of these 3 fails, we will set all the 4 field :
- cu_address
- cu_city
- cu_state
- cu_zipcode
to all whitespace so it will fail later on
business rule 1
*/
bool is_all_white_space = true;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] != ' ' )
is_all_white_space = false;
}

bool is_no_comma_separator = true;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] == ',' )
is_no_comma_separator = false;
}

bool is_not_enough_commad = false;
unsigned comma_count = 0;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] == ',' )
comma_count++;
}

if ( comma_count < 3 )
is_not_enough_commad = true;

if ( is_no_comma_separator == true ||
is_all_white_space == true ||
is_no_comma_separator == true ) {
fill_n( cus.cu_address.begin(), cus.cu_address.length(), ' ' );
fill_n( cus.cu_city.begin(), cus.cu_city.length(), ' ' );
fill_n( cus.cu_state.begin(), cus.cu_state.length(), ' ' );
fill_n( cus.cu_zipcode.begin(), cus.cu_zipcode.length(), ' ' );
} else {

vector< string > address_city_state_zipcode;
address_city_state_zipcode = util_tokenize_string( temp );
/* trim right for :
3. address
4. city
5. state
6. zipcode
*/
cus.cu_address = util_trim_right( address_city_state_zipcode[ 0 ] );
cus.cu_city = util_trim_right( address_city_state_zipcode[ 1 ] );
cus.cu_state = util_trim_right( address_city_state_zipcode[ 2 ] );
cus.cu_zipcode = util_trim_right( address_city_state_zipcode[ 3 ] );
}

/* delete all white space for :
1. ssn
2. credit 1
3. credit 2
4. credit 3
*/
util_delete_all_white_space( cus.cu_ssn );
util_delete_all_white_space( cus.cu_credit_1 );
util_delete_all_white_space( cus.cu_credit_2 );
util_delete_all_white_space( cus.cu_credit_3 );


cus_vec.push_back( cus );
}

return cus_vec;
}

void main_prog_test_all_customers( const vector< Customer >& v ) {
for ( unsigned o = 0, o_end = v.size(); o < o_end; ++o ) {
cout << "\n\n --- Customer " << o + 1 << "\n";

bool status = true;
status = v[ o ].cu_test_leading_white_space_and_null();
cout << "Status 1 " << status << endl;

status = v[ o ].cu_test_byte_field_isdigit_isalpha();
cout << "Status 2 " << status << endl;

status = v[ o ].cu_test_credit_score();
cout << "Status 3 " << status << endl;

status = v[ o ].cu_test_credit_score_mean();
cout << "Status 4 " << status << endl;
}
}

int main() {

vector< Customer > v;
v = main_prog_get_data_from_file( "in1.txt" );
main_prog_test_all_customers( v );
return 0;
}

Thursday, August 6, 2009

Cách thay đổi màu cho keyword trong gvim

Trong bài viết này mình sẽ huớng dẫn cách thay đổi màu cho keyword đồng thời chúng ta có thể add thêm keyword vào trong một colorscheme nào đó trong gvim.
Thật ra thì gvim có rất nhiều colorscheme cũng đẹp, tuy vậy nó cũng chỉ là mặc định theo một theme nào đó mà thôi, nhiều khi ta muốn thêm keyword cho GTK+, hay openGL hay STL thì chúng ta cũng không thể dùng các colorscheme đó được vì vậy cách tốt nhất là chỉnh sữa thủ công. Tuy là cách này hơi tốn thời gian một tí nhưng chúng ta sẽ có các keyword mà chúng ta ưng ý nhất :D !
- Để chỉnh sữa màu cho một colorsheme nào đó thì chúng ta phải chỉnh sữa các file sau đây, lưu ý là trong ví dụ này mình sẽ chọn syntax cho các file .cpp vì mình ngôn ngữ lập trình chính của mình là C++.
Đầu tiên chúng ta sẽ link tới các folder sau :

/usr/share/vim/vim72

Trong folder này chúng ta sẽ thấy các file :

autoload evim.vim indent mswin.vim synmenu.vim
bugreport.vim filetype.vim indent.vim optwin.vim syntax
colors ftoff.vim indoff.vim plugin tools
compiler ftplugin keymap print tutor
debian.vim ftplugin.vim lang rgb.txt vimrc_example.vim
delmenu.vim ftplugof.vim macros scripts.vim
doc gvimrc_example.vim menu.vim spell

Trong folder này thì cái mà chúng ta cần lưu ý là 2 folder : colors và syntax. Vì trong 2 folder này sẽ chứa tất cả các colorsheme ( colors folder ) và tất cả các syntax của các ngôn ngữ ( syntax folder ) :
Trong folder colors chúng ta có các file sau :

blue.vim delek.vim evening.vim murphy.vim README.txt slate.vim
darkblue.vim desert.vim koehler.vim pablo.vim ron.vim torte.vim
default.vim elflord.vim morning.vim peachpuff.vim shine.vim zellner.vim

Chúng ta có thể dễ dàng thấy rằng đây là các colorscheme mà chúng ta thuờng dùng. Ở đây mình sẽ chọn colorscheme "delek.vim", việc chọn file này là vì nó có background color là màu trắng và các keyword của nó màu cũng tương tự như màu mặc định và điều này sẽ làm cho chúng ta dễ dàng hơn trong việc chỉnh sữa và sử dụng lại.

Bây giờ ta mở file delek.vim lên :

" Vim color file
" Maintainer: David Schweikert
" Last Change: 2006 Apr 30

hi clear

let colors_name = "delek"

" Normal should come first
hi Normal guifg=Black guibg=#FFFFFF
hi Cursor guifg=bg guibg=fg
hi lCursor guifg=NONE guibg=Cyan

" Note: we never set 'term' because the defaults for B&W terminals are OK
hi DiffAdd ctermbg=LightBlue guibg=LightBlue
hi DiffChange ctermbg=LightMagenta guibg=LightMagenta
hi DiffDelete ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan
hi DiffText ctermbg=Red cterm=bold gui=bold guibg=Red
hi Directory ctermfg=DarkBlue guifg=Blue
hi ErrorMsg ctermfg=White ctermbg=DarkRed guibg=Red guifg=White
hi FoldColumn ctermfg=DarkBlue ctermbg=Grey guibg=Grey guifg=DarkBlue
hi Folded ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue
hi IncSearch cterm=reverse gui=reverse
hi LineNr ctermfg=Brown guifg=Brown
hi ModeMsg cterm=bold gui=bold
hi MoreMsg ctermfg=DarkGreen gui=bold guifg=SeaGreen
hi NonText ctermfg=Blue gui=bold guifg=gray guibg=white
hi Pmenu guibg=LightBlue
hi PmenuSel ctermfg=White ctermbg=DarkBlue guifg=White guibg=DarkBlue
hi Question ctermfg=DarkGreen gui=bold guifg=SeaGreen
hi Search ctermfg=NONE ctermbg=Yellow guibg=Yellow guifg=NONE
hi SpecialKey ctermfg=DarkBlue guifg=Blue
hi StatusLine cterm=bold ctermbg=blue ctermfg=yellow guibg=gold guifg=blue
hi StatusLineNC cterm=bold ctermbg=blue ctermfg=black guibg=gold guifg=blue
hi Title ctermfg=DarkMagenta gui=bold guifg=Magenta
hi VertSplit cterm=reverse gui=reverse
hi Visual ctermbg=NONE cterm=reverse gui=reverse guifg=Grey guibg=fg
hi VisualNOS cterm=underline,bold gui=underline,bold
hi WarningMsg ctermfg=DarkRed guifg=Red
hi WildMenu ctermfg=Black ctermbg=Yellow guibg=Yellow guifg=Black

" syntax highlighting
hi Comment cterm=NONE ctermfg=DarkRed gui=NONE guifg=#A020F0
hi Constant cterm=NONE ctermfg=DarkGreen gui=NONE guifg=#02A602
hi Identifier cterm=NONE ctermfg=DarkCyan gui=NONE guifg=cyan4
hi PreProc cterm=NONE ctermfg=DarkMagenta gui=NONE guifg=#A52A2A
hi Special cterm=NONE ctermfg=LightRed gui=NONE guifg=deeppink
hi Statement cterm=bold ctermfg=Blue gui=bold guifg=black
hi Type cterm=NONE ctermfg=Blue gui=bold guifg=black
hi GtkKeyword cterm=NONE ctermfg=Red gui=bold guifg=red
hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF
" vim: sw=2


Lưu ý là cái file này không còn là file nguyên thuỷ của ban đầu nữa, vì mình đã thêm một số keyword vào cho nó rồi. Và chúng ta có 2 dòng phải chú là :

hi GtkKeyword cterm=NONE ctermfg=Red gui=bold guifg=red
hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF

Đây là 2 dòng mình đã thêm vào, lưu ý một điều là để chỉnh sữa phải này thì chúng ta phải có đặc quyền root, vì vậy ví dụ để mở file delek.vim thì ta dùng command line sau : ( thêm vào sudo )

sudo gvim delek.vim

Và chúng ta cần ý 2 cái tên mà ta đã thêm vào GtkKeyword và StlKeyword. Hai cái tên này là do chúng ta đặt ra vì vậy các bạn muốn chỉnh sữa thế nào là tuỳ. Và đến lúc này chúng ta sẽ hơi khó hiểu ^_^ vì không biết làm sao gvim nó hiểu tiếng Anh đây! Và đến lúc này thì ta cần phải chỉnh sữa thêm thằng bạn của nó. Và thằng "bạn" của nó sẽ nằm trong folder "syntax" và có tên là cpp.vim.
Giả sử chúng ta ở đang ở trên folder chính là vim72 thì ta sẽ vào trực tiếp "syntax" folder bằng câu lệnh đơn giản sau :

cd syntax

Và đuờng dẫn của nó là :

chan@chan-laptop:/usr/share/vim/vim72$ cd syntax

Dòng này là dòng mình copy nguyên si từ terminal của mình.
Và trong folder này nó sẽ có các file sau :

2html.vim elmfilt.vim master.vim sgmldecl.vim
a2ps.vim erlang.vim matlab.vim sgmllnx.vim
a65.vim eruby.vim maxima.vim sgml.vim
aap.vim esmtprc.vim mel.vim sh.vim
abap.vim esqlc.vim messages.vim sicad.vim
abaqus.vim esterel.vim mf.vim sieve.vim
abc.vim eterm.vim mgl.vim simula.vim
abel.vim eviews.vim mgp.vim sindacmp.vim
acedb.vim exim.vim mib.vim sindaout.vim
ada.vim expect.vim mma.vim sinda.vim
aflex.vim exports.vim mmix.vim sisu.vim
ahdl.vim fasm.vim mmp.vim skill.vim
alsaconf.vim fdcc.vim modconf.vim slang.vim
amiga.vim fetchmail.vim model.vim slice.vim
aml.vim fgl.vim modsim3.vim slpconf.vim
ampl.vim flexwiki.vim modula2.vim slpreg.vim
antlr.vim focexec.vim modula3.vim slpspi.vim
ant.vim form.vim monk.vim slrnrc.vim
apachestyle.vim forth.vim moo.vim slrnsc.vim
apache.vim fortran.vim mplayerconf.vim sl.vim
arch.vim foxpro.vim mp.vim smarty.vim
art.vim framescript.vim mrxvtrc.vim smcl.vim
asm68k.vim freebasic.vim msidl.vim smil.vim
asmh8300.vim fstab.vim msmessages.vim smith.vim
asm.vim fvwm2m4.vim msql.vim sml.vim
asn.vim fvwm.vim mupad.vim sm.vim
aspperl.vim gdb.vim mush.vim snnsnet.vim
aspvbs.vim gdmo.vim muttrc.vim snnspat.vim
asterisk.vim gedcom.vim mysql.vim snnsres.vim
asteriskvm.vim gitcommit.vim named.vim snobol4.vim
atlas.vim gitconfig.vim nanorc.vim specman.vim
autohotkey.vim gitrebase.vim nasm.vim spec.vim
autoit.vim gitsendemail.vim nastran.vim spice.vim
automake.vim git.vim natural.vim splint.vim
ave.vim gkrellmrc.vim ncf.vim spup.vim
awk.vim gnuplot.vim netrc.vim spyce.vim
ayacc.vim gpg.vim netrw.vim sqlanywhere.vim
baan.vim gp.vim nosyntax.vim sqlforms.vim
basic.vim grads.vim nqc.vim sqlinformix.vim
bc.vim gretl.vim nroff.vim sqlj.vim
bdf.vim groff.vim nsis.vim sqloracle.vim
bib.vim groovy.vim objcpp.vim sql.vim
bindzone.vim group.vim objc.vim sqr.vim
blank.vim grub.vim ocaml.vim squid.vim
bst.vim gsp.vim occam.vim sshconfig.vim
btm.vim gtkrc.vim omnimark.vim sshdconfig.vim
b.vim haml.vim openroad.vim stata.vim
bzr.vim hamster.vim opl.vim stp.vim
calendar.vim haskell.vim ora.vim strace.vim
catalog.vim hastepreproc.vim pamconf.vim st.vim
cdl.vim haste.vim papp.vim sudoers.vim
cdrdaoconf.vim hb.vim pascal.vim svn.vim
cdrtoc.vim help.vim passwd.vim syncolor.vim
cfg.vim hercules.vim pcap.vim synload.vim
cf.vim hex.vim pccts.vim syntax.vim
changelog.vim hitest.vim pdf.vim sysctl.vim
change.vim hog.vim perl.vim tads.vim
chaskell.vim hostconf.vim pfmain.vim tags.vim
cheetah.vim htmlcheetah.vim pf.vim takcmp.vim
chill.vim htmldjango.vim php.vim takout.vim
chordpro.vim htmlm4.vim phtml.vim tak.vim
ch.vim htmlos.vim pic.vim tar.vim
clean.vim html.vim pike.vim tasm.vim
clipper.vim ia64.vim pilrc.vim tcl.vim
cl.vim ibasic.vim pine.vim tcsh.vim
cmake.vim icemenu.vim pinfo.vim terminfo.vim
cmusrc.vim icon.vim plaintex.vim texinfo.vim
cobol.vim idlang.vim plm.vim texmf.vim
coco.vim idl.vim plp.vim tex.vim
colortest.vim indent.vim plsql.vim tf.vim
conaryrecipe.vim inform.vim pod.vim tidy.vim
config.vim initex.vim postscr.vim tilde.vim
conf.vim initng.vim po.vim tli.vim
context.vim inittab.vim povini.vim tpp.vim
cpp.vim ipfilter.vim pov.vim trasys.vim
crm.vim ishd.vim ppd.vim trustees.vim
crontab.vim iss.vim ppwiz.vim tsalt.vim
csc.vim ist.vim prescribe.vim tsscl.vim
csh.vim jal.vim privoxy.vim tssgm.vim
csp.vim jam.vim procmail.vim tssop.vim
css.vim jargon.vim progress.vim uc.vim
cs.vim javacc.vim prolog.vim udevconf.vim
cterm.vim javascript.vim promela.vim udevperm.vim
ctrlh.vim java.vim protocols.vim udevrules.vim
cuda.vim jess.vim psf.vim uil.vim
cuplsim.vim jgraph.vim ptcap.vim updatedb.vim
cupl.vim jproperties.vim purifylog.vim valgrind.vim
c.vim jsp.vim pyrex.vim vb.vim
cvsrc.vim kconfig.vim python.vim vera.vim
cvs.vim kix.vim qf.vim verilogams.vim
cweb.vim kscript.vim quake.vim verilog.vim
cynlib.vim kwt.vim racc.vim vgrindefs.vim
cynpp.vim lace.vim radiance.vim vhdl.vim
dcd.vim latte.vim ratpoison.vim viminfo.vim
dcl.vim ldapconf.vim rcslog.vim vim.vim
debchangelog.vim ldif.vim rcs.vim virata.vim
debcontrol.vim ld.vim rc.vim vmasm.vim
debsources.vim lex.vim readline.vim voscm.vim
def.vim lftp.vim README.txt vrml.vim
denyhosts.vim lhaskell.vim rebol.vim vsejcl.vim
desc.vim libao.vim registry.vim wdiff.vim
desktop.vim lifelines.vim remind.vim webmacro.vim
dictconf.vim lilo.vim resolv.vim web.vim
dictdconf.vim limits.vim reva.vim wget.vim
diff.vim lisp.vim rexx.vim whitespace.vim
dircolors.vim litestep.vim rhelp.vim winbatch.vim
diva.vim lite.vim rib.vim wml.vim
django.vim loginaccess.vim rnc.vim wsh.vim
dns.vim logindefs.vim rnoweb.vim wsml.vim
docbksgml.vim logtalk.vim robots.vim wvdial.vim
docbk.vim lotos.vim rpcgen.vim xbl.vim
docbkxml.vim lout.vim rpl.vim xdefaults.vim
dosbatch.vim lpc.vim rst.vim xf86conf.vim
dosini.vim lprolog.vim rtf.vim xhtml.vim
dot.vim lscript.vim ruby.vim xinetd.vim
doxygen.vim lsl.vim r.vim xkb.vim
dracula.vim lss.vim samba.vim xmath.vim
dsl.vim lua.vim sass.vim xml.vim
dtd.vim lynx.vim sas.vim xmodmap.vim
dtml.vim m4.vim sather.vim xpm2.vim
dtrace.vim mailaliases.vim scheme.vim xpm.vim
d.vim mailcap.vim scilab.vim xquery.vim
dylanintr.vim mail.vim screen.vim xsd.vim
dylanlid.vim make.vim sdl.vim xslt.vim
dylan.vim manconf.vim sd.vim xs.vim
ecd.vim manual.vim sed.vim xxd.vim
edif.vim man.vim sendpr.vim yacc.vim
eiffel.vim maple.vim sensors.vim yaml.vim
elf.vim masm.vim services.vim z8a.vim
elinks.vim mason.vim setserial.vim zsh.vim


Nhưng cái mà mình quan tâm ở đây chỉ là thằng "cpp.vim", cái đám còn lại thì chúng ta không cần quan tâm. Nhưng nếu bạn là một lập trình viên Java hay bất cứ ngôn ngữ nào đó thì các bạn có thể chọn file của ngôn ngữ đó mà chỉnh sữa. Thao tác nó cũng tương tự mà thôi.
Bây giờ chúng ta sẽ mở file cpp.vim lên ta sẽ thấy như sau :

" Vim syntax file
" Language: C++
" Maintainer: Ken Shan
" Last Change: 2002 Jul 15

" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif

" Read the C syntax to start with
if version < 600
so :p:h/c.vim
else
runtime! syntax/c.vim
unlet b:current_syntax
endif

" C++ extentions
syn keyword cppStatement new delete this friend using
syn keyword cppAccess public protected private
syn keyword cppType inline virtual explicit export bool wchar_t
syn keyword cppExceptions throw try catch
syn keyword cppOperator operator typeid
syn keyword cppOperator and bitor or xor compl bitand and_eq or_eq xor_eq not not_eq
syn match cppCast "\<\(const\|static\|dynamic\|reinterpret\)_cast\s*<"me=e-1
syn match cppCast "\<\(const\|static\|dynamic\|reinterpret\)_cast\s*$"
syn keyword cppStorageClass mutable
syn keyword cppStructure class typename template namespace
syn keyword cppNumber NPOS
syn keyword cppBoolean true false
syn keyword gtkKeyword GObject GInitiallyUnowned GtkObject GtkWidget GtkContainer GtkBin GtkWindow GtkDialog GtkAboutDialog GtkColorSelectionDialog GtkFileChooserDialog GtkFileSelection GtkFontSelectionDialog GtkInputDialog GtkMessageDialog GtkPageSetupUnixDialog GtkPrintUnixDialog GtkRecentChooserDialog GtkAssistant GtkPlug GtkAlignment GtkFrame GtkAspectFrame GtkButton GtkToggleButton GtkCheckButton GtkRadioButton GtkColorButton GtkFontButton GtkLinkButton GtkOptionMenu GtkScaleButton GtkVolumeButton GtkItem GtkMenuItem GtkCheckMenuItem GtkRadioMenuItem GtkImageMenuItem GtkSeparatorMenuItem GtkTearoffMenuItem GtkListItem GtkTreeItem GtkComboBox GtkComboBoxEntry GtkEventBox GtkExpander GtkHandleBox GtkToolItem GtkToolButton GtkMenuToolButton GtkToggleToolButton GtkRadioToolButton GtkSeparatorToolItem GtkScrolledWindow GtkViewport GtkBox GtkButtonBox GtkHButtonBox GtkVButtonBox GtkVBox GtkColorSelection GtkFileChooserWidget GtkFontSelection GtkGammaCurve GtkRecentChooserWidget GtkHBox GtkCombo GtkFileChooserButton GtkStatusbar GtkCList GtkCTree GtkFixed GtkPaned GtkHPaned GtkVPaned GtkIconView GtkLayout GtkList GtkMenuShell GtkMenuBar GtkMenu GtkRecentChooserMenu GtkNotebook GtkSocket GtkTable GtkTextView GtkToolbar GtkTree GtkTreeView GtkMisc GtkLabel GtkAccelLabel GtkTipsQuery GtkArrow GtkImage GtkPixmap GtkCalendar GtkCellView GtkDrawingArea GtkCurve GtkEntry GtkSpinButton GtkRuler GtkHRuler GtkVRuler GtkRange GtkScale GtkHScale GtkVScale GtkScrollbar GtkHScrollbar GtkVScrollbar GtkSeparator GtkHSeparator GtkVSeparator GtkHSV GtkInvisible GtkOldEditable GtkText GtkPreview GtkProgress GtkProgressBar GtkAdjustment GtkCellRenderer GtkCellRendererText GtkCellRendererAccel GtkCellRendererCombo GtkCellRendererSpin GtkCellRendererPixbuf GtkCellRendererProgress GtkCellRendererToggle GtkFileFilter GtkItemFactory GtkTooltips GtkTreeViewColumn GtkRecentFilter GtkAccelGroup GtkAccelMap AtkObject GtkAccessible GtkAction GtkToggleAction GtkRadioAction GtkRecentAction GtkActionGroup GtkBuilder GtkClipboard GtkEntryCompletion GtkIconFactory GtkIconTheme GtkIMContext GtkIMContextSimple GtkIMMulticontext GtkListStore GMountOperation GtkMountOperation GtkPageSetup GtkPrinter GtkPrintContext GtkPrintJob GtkPrintOperation GtkPrintSettings GtkRcStyle GtkRecentManager GtkSettings GtkSizeGroup GtkStatusIcon GtkStyle GtkTextBuffer GtkTextChildAnchor GtkTextMark GtkTextTag GtkTextTagTable GtkTreeModelFilter GtkTreeModelSort GtkTreeSelection GtkTreeStore GtkUIManager GtkWindowGroup GtkTooltip GtkPrintBackend GInterface GtkBuildable GtkActivatable GtkOrientable GtkCellEditable GtkCellLayout GtkEditable GtkFileChooser GtkTreeModel GtkTreeDragSource GtkTreeDragDest GtkTreeSortable GtkPrintOperationPreview GtkRecentChooser GtkToolShell
syn keyword stlKeyword vector list deque map multimap set multiset string stack iterator streambuf bitset ostream istream stringstream ostringstream istringstream const_iterator ifstream ofstream fstream

" The minimum and maximum operators in GNU C++
syn match cppMinMax "[<>]?"

" Default highlighting
if version >= 508 || !exists("did_cpp_syntax_inits")
if version < 508
let did_cpp_syntax_inits = 1
command -nargs=+ HiLink hi link
else
command -nargs=+ HiLink hi def link
endif
HiLink cppAccess cppStatement
HiLink cppCast cppStatement
HiLink cppExceptions Exception
HiLink cppOperator Operator
HiLink cppStatement Statement
HiLink cppType Type
HiLink cppStorageClass StorageClass
HiLink cppStructure Structure
HiLink cppNumber Number
HiLink cppBoolean Boolean
HiLink gtkKeyword GtkKeyword
HiLink stlKeyword StlKeyword
delcommand HiLink
endif

let b:current_syntax = "cpp"

" vim: ts=8


Và 2 dòng mà chúng ta cần chú ý là 2 dòng bắt đầu bằng :

syn keyword gtkKeyword ...

Sữ dụng cú pháp này chúng ta đã định nghĩa một tập các keywords khác cho các file .cpp. Lưu ý là cái dấu "..." là nơi chúng ta thêm các keyword vào đó. Mỗi keywords sẽ cách nhau một "space". Mình sẽ lấy thằng stlKeyword làm ví dụ vì nó cũng không có nhiều keyword lắm. Ví dụ :

syn keyword stlKeyword vector list deque map multimap set multiset string stack iterator streambuf bitset ostream istream stringstream ostringstream istringstream const_iterator ifstream ofstream fstream

Nhưng công việc vẫn chưa xong, thằng stlKeyword ở đây chỉ đóng vai trò như một alias cho thằng mà chúng ta đã thêm vào StlKeyword mà thôi. Lý do có thêm thằng alias này là vì trong vim nó sử dụng các comment, keyword như một danh từ chung cho toàn các ngôn ngữ, vì vậy để tái sử dụng thì chúng phải có các danh từ chung này. Ví dụ cho C++ ta có alias "cppStatement" cho Java ta có "javaStatement".... Nhưng khi chúng ta đến dòng này :

HiLink cppStatement Statement

Thì chúng ta hiểu ra rằng à !!! thì ra là vậy ^_^ !
Nhưng đối với StlKeyword và GtkKeyword thì nó chỉ tồn tại trong C/C++ mà thôi, vì vậy đặt thêm thằng alias cũng chẳng mang ý nghĩa gì nhiều lắm. Nhưng để cho giống cấu trúc của file syntax thì ta thêm vào vậy thôi. Lưu ý thằng alias toàn bộ là viết thường trong khi thằng chúng ta sử dụng sẽ có chữ cái Hoa viết đầu :
stlKeyword vs StlKeyword
Tiếp theo là dòng :

HiLink stlKeyword StlKeyword

Khi ta thêm dòng này thì thằng trong folder colors "delek.vim" mới bắt đầu có hiệu lực.
Save lại chúng ta sẽ có màu mà chúng ta đã chọn.
Bây giờ ta quay lại với file delek.vim một chúng để tìm hiểu làm sao thêm một màu mới cho nó :
Ta để ý dòng :

hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF

Ở đây ta không cần quan tâm thằng cterm và ctermfg, cái chúng ta cần chỉ là thằng gui và guifg mà thôi.
gui : là kiểu và có giá trị ( bold, italic, underline )
guifg : là các màu chúng ta định nghĩa, nó có thể ở dạng chữ hay ở dạng hexa deximal.
Những con số này thì chúng ta có thể tra cứu online hay sử dụng một text editor khác, vào trong phần chọn màu của nó và chọn. Ở đây mình dùng Codeblock để chọn màu.
Vậy là chúng ta xong, bây giờ hãy vào colorsheme duới tab "edit" và chọn lại colorsheme delek.vim và enjoy ^_^ !

Thursday, July 9, 2009

Chương trình chơi nhạc đơn giản trên Linux ( ver 1.0 ) GTK+

Đây là một chương trình chơi nhạc mp3 nhỏ mà mình mới viết hôm nay. Chức năng thì cực kì giới hạn T_T, chỉ chơi đuợc đúng một file và còn một số chức năng khác như dừng, lặp lại, click vào treeview để lặp lại.... Vì mình chỉ viết trong vỏn vẹn một ngày cho nên chắc chắn bug là khó tránh khỏi. Dù vậy mình cũng post nó lên đây coi như thói quen làm việc từng ngày của mình, mình chắc chắn là sẽ update nó lên nhiều. Các chính là mình chỉ mới bắt đầu tìm hiểu gstreamer( multimedia framework ) cho nên chương trình còn hạn chế rất nhiều. Lúc này mình cũng còn đang phân vân không biết nên dùng SDL( cross-platform ) hay thằng gstreamer này vì cả 2 thằng đều có đặc điểm hay riêng cả T_T.

Các bạn có thể down toàn bộ source ở đây chỉ 1 file ^_^
source

Để compile chương trình các bạn dùng dòng lệnh sau :

g++ main.cpp -o main `pkg-config --cflags --libs gtk+-2.0 gstreamer-0.10`


Và đây là screenshot :
Photobucket

Wednesday, July 8, 2009

Chương trình IDE đơn giản trên Linux với GTK+ ( ver. 1.1 )

Đây là phiên bản thứ hai mà mình viết, có thêm code-statistics và mình vừa edit lại một số lỗi nhỏ ! Các bạn có thể download toàn bộ chương trình ở đây :D !

source

Dịch chương trình với dòng lệnh sau nhé :

g++ main.cpp ch_type.h token.h statistics.h -o main -Wall -pedantic -O3
`pkg-config --cflags --libs gtk+-2.0 gtksourceview-2.0`


Và đây là screenshot của nó :
Photobucket

Photobucket

How to implement Auto Pointer C++

In C++, auto_ptr<> is a smart pointer which automatically destroy itself when the program ends. Implementing an auto_ptr class is really easy and straightforward.

#include <iostream>
#include <cstdlib>

template< class T >
class AutoPointer
{
public :
explicit AutoPointer( T* rhs = NULL )
:is_owner( rhs != NULL ), g( rhs )
{ }

AutoPointer( AutoPointer& rhs )
:is_owner( rhs.is_owner )
{
g = rhs.release();
}

~AutoPointer()
{
free_mem();
}

const AutoPointer& operator =( AutoPointer& rhs )
{
if ( &rhs != this )
{
T* other = rhs.deref();
if ( other != g )
{
free_mem();
is_owner = rhs.is_owner;
}
else if ( rhs.is_owner )
{
is_owner = true;
}
g = rhs.release();
}
return *this;
}

T& operator *() const
{
return *deref();
}

T* operator ->() const
{
return deref();
}

T* deref() const
{
return g;
}

T* release()
{
is_owner = false;
return g;
}

private:
T* g;
bool is_owner;
void free_mem()
{
if ( is_owner )
delete g;
}
};

struct Integer
{
Integer( int a ):x( a )
{ }

~Integer()
{
std::cout << "DESTRUCT " << x << '\n';
}

int x;
};


int main( )
{
AutoPointer< Integer > p1( new Integer( 3 ) );
AutoPointer< Integer > p2 = p1;
AutoPointer< Integer > p3;

std::cout << ( *p1 ).x << " " << ( *p2 ).x << '\n';
p3 = p1;
std::cout << p1->x << " " << p2->x << " " << p3->x << '\n';
// 3 is owned by p2.

AutoPointer< Integer > p4( new Integer( 4 ) );
std::cout << p1->x << " " << p2->x << " " << p3->x << " " << p4->x << '\n';
p2 = p4;

std::cout << "3 is no longer owned! p1 and p3 are stale!!!" << '\n';
std::cout << p2->x << " " << p4->x << std::endl;

return 0;
}

Tuesday, July 7, 2009

Simple IDE with GTK+

Đây là chương trình giả tạo IDE đơn giản mà mình viết dùng C/C++ với library GTK+. Nó cũng chẳng có chức năng gì nhiều cả. Nhưng cái chính mình viết nó là để học tập, và mình sẽ còn tiếp tục phát triển nó. Hi vọng có một ngày nó sẽ hoàn thiện hơn.
Chương trình chỉ vọn vẹn có một file ^_^, tuy vậy nó hơi dài nên mình sẽ post lên đây. Các bạn có thể download chương trình tại đây nhé.
source

Vì mình dùng thư viện hỗ trợ gtksourceview-2.0 nên các bạn muốn dịch được thì phải download thằng này về rồi install hoặc install dưới synaptic package manager cũng đuợc.
Các bạn dịch chương trình với lệnh sau :

g++ main.cpp -o main -Wall -pedantic -O3 `pkg-config --cflags --libs gtk+-2.0 gtksourceview-2.0`

Thursday, July 2, 2009

How to skip '\n' when working with number and char ?

Number and character are sometimes really annoying when being mixed together.
Simple trick could solve the problem :

#include <iostream>
#include <string>

template< typename charT >
class Skipper
{
public :
typedef charT char_type;
Skipper( char_type delim ):delim_( delim )
{ }
template< typename traits >
void operator ()( std::basic_istream< charT, traits >& ) const;
private :
char_type delim_;
};

template< typename charT >
template< typename traits >
void Skipper< charT >::operator ()( std::basic_istream< charT, traits >& stream ) const
{
char_type c;
while ( stream.get( c ) && c != delim_ )
;
}


template< typename charT, typename traits >
std::basic_istream< charT, traits >& operator >>( std::basic_istream< charT, traits >& stream,
const Skipper< charT >& f )
{
f( stream );
return stream;
}

template< typename charT >
Skipper< charT > skip( charT c )
{
return Skipper< charT >( c );
}

int main()
{
int x, y;
char c[ 10 ];
std::string next;


std::cout << "Please enter a number : \n";
std::cin >> x >> skip( '\n' );

std::cout << "Then, please enter a character : \n";
std::cin.getline( c, 10 );

std::cout << " RESULT IS : \n";

std::cout << x << "\n";
std::cout << c << "\n";
return 0;
}

Print string backward

Problem : input a string then print it backward.
Solution : There are many solution for this problem I think. However, personally I like this one the most. Clean and Clear ! Enjoy and have fun :D

#include <iostream>
#include <stack>
#include <string>

typedef std::stack< std::string > scon;

void cut_string( const std::string& str, scon* sentence, const std::string& del )
{
std::string::size_type start = 0;
std::string::size_type end = str.find_first_of(del, start);
std::string::size_type length = str.length();
std::string word;

while( std::string::npos != end && end < length )
{
word = str.substr( start, end - start );
sentence->push( word );
start = end + 1;
end = str.find_first_of( del, start );
}

end = str.find_last_of( " " ) + 1;
sentence->push( str.substr( end ) );
}

void print_backward( scon* c )
{
while ( !c->empty() )
{
std::cout << c->top() << " ";
c->pop();
}
}

int main()
{
scon c;
std::string sentence;

std::cout << "Enter a sentence : \n";
getline( std::cin, sentence );

cut_string( sentence, &c, " " );

print_backward( &c );

return 0;
}

A simple graphic user interface Text-Editor

Đây là một chương trình Text Editor đơn giản nhất "có thể" ^_^ mà mình viết nháp trước khi chuyển nó thành 1 IDE thực sự. Vì đây là chương trình đầu tiên nên chắc nó chẳng có chức năng gì thú vị cả. Nhưng mình nghĩ dù gì thì nó cũng có ích đối với các bạn mới bắt đầu học GTK+ vì vậy mình post nó lên đây để các bạn có thể tham khảo. Code chỉ có vọn vẻn 1 file ^_^ tuy vậy nó cũng khá dài nên mình post nó lên host này, các bạn có thể down load chương trình ở đây nhé :
source

Wednesday, July 1, 2009

1000 ! Factorial.

Large factorial is a problem for a single variable but for an array, the problem is solved easily :D

#include <iostream>
#include <cmath>
#include <vector>

struct factorial {
factorial( unsigned x ):x( x ), digits( static_cast< int >( cal_digs( x ) ) + 1, 0 ) {
find_fact();
}

double cal_digs( unsigned N ) {
double appr = 0.0;
for( unsigned di = 2; di <= N; ++di )
appr += std::log10( di );
return appr;
}

void find_fact() {
unsigned rem, tmp, val;
digits.at( 0 ) = 1;
double appr = 0.0;
for( unsigned o = 2; o <= x; ++o ) {
rem = 0;
appr += std::log10( o );
tmp = static_cast< unsigned >( appr );
for( unsigned o1 = 0; o1 <= tmp; ++o1 ) {
val = ( digits.at( o1 ) * o ) + rem;
rem = val / 10;
digits.at( o1 ) = val % 10;
}
}
}

std::ostream& out( std::ostream& o ) const {
for( std::vector< unsigned >::const_reverse_iterator cib = digits.rbegin(), cie = digits.rend(); cib != cie; ++cib )
o << *cib;
return o << std::endl;
}

private :
unsigned x;
std::vector< unsigned > digits;
};

std::ostream& operator <<( std::ostream& o, const factorial& fa ) {
return fa.out( o );
}

int main()
{
factorial f( 10000 );
std::cout << f << "\n";
}

How to derived operator >> from Base class !

Simple trick :
D ! Have fun !

#include <iostream>

class Base
{
protected :
int x;
public :
friend std::istream &operator >>( std::istream &is, Base &b )
{
is >> b.x;
return is;
}
};



class Derived : public Base
{
private :
int y;

public :
friend std::istream &operator >>( std::istream &is, Derived &d )
{
is >> static_cast< Base & >( d );
is >> d.y;
return is;
}
};


int main()
{
Derived d;
std::cin >> d;

return 0;
}

How to create a widget from scratch ?

Simple Widget from scratch, code from Foundation of GTK+


#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtkwidget.h>
#include <gtk/gtk.h>

G_BEGIN_DECLS

#define MY_MARQUEE_TYPE ( my_marquee_get_type() )
#define MY_MARQUEE(obj) ( G_TYPE_CHECK_INSTANCE_CAST( ( obj ), MY_MARQUEE_TYPE, MyMarquee ) )
#define MY_MARQUEE_CLASS(klass) ( G_TYPE_CHECK_CLASS_CAST( ( klass ), MY_MARQUEE_TYPE, MyMarqueeClass ) )
#define IS_MY_MARQUEE(obj) ( G_TYPE_CHECK_INSTANCE_TYPE( ( obj ), MY_MARQUEE_TYPE ) )
#define IS_MY_MARQUEE_CLASS(klass) ( G_TYPE_CHECK_CLASS_TYPE( ( klass ), MY_MARQUEE_TYPE ) )

typedef struct _MyMarquee MyMarquee;
typedef struct _MyMarqueeClass MyMarqueeClass;

struct _MyMarquee
{
GtkWidget widget;
};

struct _MyMarqueeClass
{
GtkWidgetClass parent_class;
};

GType my_marquee_get_type( void ) G_GNUC_CONST;
GtkWidget* my_marquee_new( void );
void my_marquee_set_message( MyMarquee *marquee, const gchar *message );
char* my_marquee_get_message( MyMarquee *marquee );
void my_marquee_set_speed( MyMarquee *marquee, int speed );
gint my_marquee_get_speed( MyMarquee *marquee );

void my_marquee_slide (MyMarquee *marquee);

G_END_DECLS


#define MARQUEE_MIN_WIDTH 300

static void my_marquee_class_init (MyMarqueeClass*);
static void my_marquee_init (MyMarquee*);
static void my_marquee_get_property (GObject*, guint, GValue*, GParamSpec*);
static void my_marquee_set_property (GObject*, guint, const GValue*, GParamSpec*);

static void my_marquee_realize (GtkWidget*);
static void my_marquee_size_request (GtkWidget*, GtkRequisition*);
static void my_marquee_size_allocate (GtkWidget*, GtkAllocation*);
static gint my_marquee_expose (GtkWidget*, GdkEventExpose*);

#define MY_MARQUEE_GET_PRIVATE( obj ) ( G_TYPE_INSTANCE_GET_PRIVATE( ( obj ), MY_MARQUEE_TYPE, MyMarqueePrivate ) )

typedef struct _MyMarqueePrivate MyMarqueePrivate;

struct _MyMarqueePrivate
{
gchar *message;
int speed;
int current_x;
};

enum
{
PROP_0,
PROP_MESSAGE,
PROP_SPEED
};

/* Get a GType that corresponds to MyMarquee. The first time this function is
* called (on object instantiation), the type is registered. */
GType my_marquee_get_type ()
{
static GType marquee_type = 0;

if ( !marquee_type )
{
static const GTypeInfo marquee_info =
{
sizeof( MyMarqueeClass ),
NULL,
NULL,
( GClassInitFunc )my_marquee_class_init,
NULL,
NULL,
sizeof( MyMarquee ),
0,
( GInstanceInitFunc )my_marquee_init,
};

marquee_type = g_type_register_static( GTK_TYPE_WIDGET,
"MyMarquee",
&marquee_info,
static_cast< GTypeFlags >( 0 ) );
}

return marquee_type;
}

/* Initialize the MyMarqueeClass class by overriding standard functions,
* registering a private class and setting up signals and properties. */
static void my_marquee_class_init( MyMarqueeClass *klass )
{
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;

gobject_class = ( GObjectClass* ) klass;
widget_class = ( GtkWidgetClass* ) klass;

/* Override the standard functions for setting and retrieving properties. */
gobject_class->set_property = my_marquee_set_property;
gobject_class->get_property = my_marquee_get_property;

/* Override the standard functions for realize, expose, and size changes. */
widget_class->realize = my_marquee_realize;
widget_class->expose_event = my_marquee_expose;
widget_class->size_request = my_marquee_size_request;
widget_class->size_allocate = my_marquee_size_allocate;

/* Add MyMarqueePrivate as a private data class of MyMarqueeClass. */
g_type_class_add_private (klass, sizeof (MyMarqueePrivate));

/* Register four GObject properties, the message and the speed. */
g_object_class_install_property( gobject_class,
PROP_MESSAGE,
g_param_spec_string( "message",
"Marquee Message",
"The message to scroll",
"",
( GParamFlags )G_PARAM_READWRITE ) );

g_object_class_install_property( gobject_class,
PROP_SPEED,
g_param_spec_int( "speed",
"Speed of the Marquee",
"The percentage of movement every second",
1, 50, 25,
( GParamFlags )G_PARAM_READWRITE ) );
}

/* Initialize the actual MyMarquee widget. This function is used to setup
* the initial view of the widget and set necessary properties. */
static void my_marquee_init( MyMarquee *marquee )
{
MyMarqueePrivate *priv = MY_MARQUEE_GET_PRIVATE( marquee );

priv->current_x = MARQUEE_MIN_WIDTH;
priv->speed = 25;
}

/* This function is called when the programmer gives a new value for a widget
* property with g_object_set(). */
static void my_marquee_set_property( GObject *object,
unsigned prop_id,
const GValue *value,
GParamSpec *pspec )
{
MyMarquee *marquee = MY_MARQUEE (object);

switch ( prop_id )
{
case PROP_MESSAGE :
my_marquee_set_message( marquee, g_value_get_string( value ) );
break;

case PROP_SPEED :
my_marquee_set_speed( marquee, g_value_get_int( value ) );
break;

default :
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
break;
}
}

/* This function is called when the programmer requests the value of a widget
* property with g_object_get(). */
static void my_marquee_get_property( GObject *object,
unsigned prop_id,
GValue *value,
GParamSpec *pspec)
{
MyMarquee *marquee = MY_MARQUEE( object );
MyMarqueePrivate *priv = MY_MARQUEE_GET_PRIVATE( marquee );

switch ( prop_id )
{
case PROP_MESSAGE:
g_value_set_string (value, priv->message);
break;

case PROP_SPEED:
g_value_set_int (value, priv->speed);
break;

default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}

/* Create and return a new instance of the MyMarquee widget. */
GtkWidget* my_marquee_new()
{
return GTK_WIDGET( g_object_new( my_marquee_get_type(), NULL ) );
}

/* Called when the widget is realized. This usually happens when you call
* gtk_widget_show() on the widget. */
static void my_marquee_realize( GtkWidget *widget )
{
MyMarquee *marquee;
GdkWindowAttr attributes;
int attr_mask;

g_return_if_fail( widget != NULL );
g_return_if_fail( IS_MY_MARQUEE( widget ) );

/* Set the GTK_REALIZED flag so it is marked as realized. */
GTK_WIDGET_SET_FLAGS( widget, GTK_REALIZED );
marquee = MY_MARQUEE( widget );

/* Create a new GtkWindowAttr object that will hold info about the GdkWindow. */
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.event_mask = gtk_widget_get_events (widget);
attributes.event_mask |= ( GDK_EXPOSURE_MASK );
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);

/* Create a new GdkWindow for the widget. */
attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new( widget->parent->window, &attributes, attr_mask );
gdk_window_set_user_data( widget->window, marquee );

/* Attach a style to the GdkWindow and draw a background color. */
widget->style = gtk_style_attach( widget->style, widget->window );
gtk_style_set_background( widget->style, widget->window, GTK_STATE_NORMAL );
gdk_window_show( widget->window );
}

/* Handle size requests for the widget. This function forces the widget to have
* an initial size set according to the predefined width and the font size. */
static void my_marquee_size_request( GtkWidget *widget,
GtkRequisition *requisition )
{
PangoFontDescription *fd;

g_return_if_fail( widget != NULL || requisition != NULL );
g_return_if_fail( IS_MY_MARQUEE( widget ) );

fd = widget->style->font_desc;
requisition->width = MARQUEE_MIN_WIDTH;
requisition->height = ( pango_font_description_get_size( fd ) / PANGO_SCALE ) + 10;
}

/* Handle size allocations for the widget. This does the actual resizing of the
* widget to the requested allocation. */
static void my_marquee_size_allocate( GtkWidget *widget,
GtkAllocation *allocation)
{
MyMarquee *marquee;

g_return_if_fail( widget != NULL || allocation != NULL );
g_return_if_fail( IS_MY_MARQUEE( widget ) );

widget->allocation = *allocation;
marquee = MY_MARQUEE( widget );

if ( GTK_WIDGET_REALIZED( widget ) )
{
gdk_window_move_resize( widget->window,
allocation->x,
allocation->y,
allocation->width,
allocation->height );
}
}

/* This function is called when an expose-event occurs on the widget. This means
* that a part of the widget that was previously hidden is shown. */
static int my_marquee_expose( GtkWidget *widget,
GdkEventExpose *event )
{
PangoFontDescription *fd;
MyMarquee *marquee;
MyMarqueePrivate *priv;
PangoLayout *layout;
PangoContext *context;
int width, height;

g_return_val_if_fail( widget != NULL || event != NULL, FALSE );
g_return_val_if_fail( IS_MY_MARQUEE( widget ), FALSE );

if ( event->count > 0 )
return TRUE;

marquee = MY_MARQUEE( widget );
priv = MY_MARQUEE_GET_PRIVATE( marquee );
fd = widget->style->font_desc;
context = gdk_pango_context_get();
layout = pango_layout_new( context );
g_object_unref( context );

/* Create a new PangoLayout out of the message with the given font. */
pango_layout_set_font_description( layout, fd );
pango_layout_set_text( layout, priv->message, -1 );
pango_layout_get_size( layout, &width, &height );

/* Clear the text from the background of the widget. */
gdk_window_clear_area( widget->window,
0,
0,
widget->allocation.width,
widget->allocation.height);

/* Draw the PangoLayout on the widget, which is the message text. */
gdk_draw_layout( widget->window,
widget->style->fg_gc[ widget->state ],
priv->current_x,
( widget->allocation.height - ( height / PANGO_SCALE ) ) / 2,
layout );

return TRUE;
}

/* Move the message "speed" pixels to the left or wrap the message around. */
void my_marquee_slide( MyMarquee *marquee )
{
PangoFontDescription *fd;
GtkWidget *widget;
MyMarqueePrivate *priv;
PangoLayout *layout;
PangoContext *context;
int width, height;

g_return_if_fail( marquee != NULL );
g_return_if_fail( IS_MY_MARQUEE( marquee ) );

widget = GTK_WIDGET( marquee );
priv = MY_MARQUEE_GET_PRIVATE( marquee );
fd = widget->style->font_desc;
context = gdk_pango_context_get();
layout = pango_layout_new( context );
g_object_unref( context );

/* Create a new PangoLayout out of the message with the given font. */
pango_layout_set_font_description( layout, fd );
pango_layout_set_text( layout, priv->message, -1 );
pango_layout_get_size( layout, &width, &height );

/* Clear the text from the background of the widget. */
gdk_window_clear_area( widget->window,
0,
0,
widget->allocation.width,
widget->allocation.height );

/* Scroll the message "speed" pixels to the left or wrap around. */
priv->current_x = priv->current_x - priv->speed;
if ( ( priv->current_x + ( width / PANGO_SCALE ) ) <= 0 )
priv->current_x = widget->allocation.width;

/* Draw the PangoLayout on the widget, which is the message text. */
gdk_draw_layout( widget->window,
widget->style->fg_gc[widget->state],
priv->current_x,
( widget->allocation.height - ( height / PANGO_SCALE ) ) / 2,
layout );
}

/* Set the message that is displayed by the widget. */
void my_marquee_set_message( MyMarquee *marquee,
const char *message )
{
MyMarqueePrivate *priv = MY_MARQUEE_GET_PRIVATE( marquee );

if ( priv->message )
{
g_free( priv->message );
priv->message = NULL;
}

priv->message = g_strdup( message );
}

/* Retrieve the message that is displayed by the widget. You must free this
* string after you are done using it! */
char* my_marquee_get_message( MyMarquee *marquee )
{
return g_strdup( MY_MARQUEE_GET_PRIVATE( marquee )->message );
}

/* Set the number of pixels that the message will scroll. */
void my_marquee_set_speed( MyMarquee *marquee,
int speed )
{
MyMarqueePrivate *priv = MY_MARQUEE_GET_PRIVATE( marquee );
priv->speed = speed;
}

/* Retrieve the number of pixels that the message will scroll. */
int my_marquee_get_speed( MyMarquee *marquee )
{
return MY_MARQUEE_GET_PRIVATE( marquee )->speed;
}



int main (int argc,
char *argv[])
{
GtkWidget *window, *marquee;
PangoFontDescription *fd;

gtk_init( &argc, &argv );

window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_title( GTK_WINDOW( window ), "GtkMarquee" );
gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );

g_signal_connect( G_OBJECT( window ),
"destroy",
G_CALLBACK( gtk_main_quit ),
NULL );

fd = pango_font_description_from_string( "Monospace 30" );
marquee = my_marquee_new();
gtk_widget_modify_font( marquee, fd );
my_marquee_set_message( MY_MARQUEE( marquee ), "Wheeeee!" );
my_marquee_set_speed( MY_MARQUEE( marquee ), 10 );
pango_font_description_free( fd );

g_timeout_add( 150, ( GSourceFunc )my_marquee_slide, ( gpointer ) marquee );

gtk_container_add( GTK_CONTAINER( window ), marquee );
gtk_widget_show_all( window );

gtk_main();

return 0;
}




Compiled with :
g++ main.cpp -o main -Wall -pedantic -O3 `pkg-config --cflags --libs gtk+-2.0`

Chương trình lấy thông tin của package trong Ubuntu ( GTK+ )

Đây là chương trình dùng để lấy thông tin của một package, cái ý tưởng chính của chương trình này là sử dụng shell command :

string command_line = "/usr/bin/apt-cache show ";


Và chương trình này tuy là mình viết nhưng mình đã có tham khảo ý tưởng từ một bạn ở trong forum
http://www.gtkforums.com/ chứ không phải một 100% là mình nghĩ ra.
Hi vọng nó giúp ích cho các bạn mới học.

Các bạn có thể down chương trình theo link sau đây :
source

Các bạn compile chương trình với dòng lệnh sau :

g++ main.cpp -o main `pkg-config --cflags --libs gtk+-2.0`


Và đây là screenshot :
Photobucket

A simple dictionary using GTK+

Đây là một chương trình từ điển đơn giản mà mình viết bằng C++ với library GTK+ trên Linux. Vì là chương trình đơn giản nên nó không có database gì hết, nhưng nó minh hoạ cách dùng GtkTreeView trong GTK+ và std::map<> trong STL C++. Chương trình chỉ có 2 file : DictionaryDatabase.h và main.cpp. Hi vọng nó có thể giúp ích cho các bạn mới vừa bắt đầu đến với C++ cũng như GTK+.
Đây là toàn bộ source code của chương trình, các bạn có thể download tại đây :
source

Và đây là screenshot :
Photobucket