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