Monday, August 28, 2006

C++ note: int to string

import <string>
import <sstream>

using namespace std;

int main() {
...string s;
...int a=1;
...stringstream ss;
...ss << a;
...
ss >> s;
}

also, use atoi or strtol for string to int (cstdlib).
use s = c to assign directly from C string to string, and use s.c_str() to get c string from string

Saturday, July 08, 2006

Python note: __hash__

__hash__ provides the hash code for an object. It is used under two circumstances: when the object is put in a dictionary; or when hash() built-in function is called.

There is a requirement for this method - two objects should have the same hash when their __cmp__ returns zero (they are equal). Thus when a class does not provide __cmp__ member function, it should not provide __hash__.

Friday, July 07, 2006

VIM note: tabs

In VIM 7, tab view is supported.

To open a new tab, use :tabnew
To navigate among tabs, use 'gt'
To close a tab, use ':tabclose'

Tuesday, June 06, 2006

Python note: unicode example (switch utf to gb2312)

This is a script to switch files from unicode to gb2312

# gb2utf - switch encoding between text
# Yue Zhang 2006
import sys
iFile = open(sys.argv[1])
oFile = open(sys.argv[2], "w")
sLine = iFile.readline()
while sLine:
...try:
......uLine = sLine.decode("gb2312")
...except UnicodeDecodeError:
......sLine = iFile.readline()
......continue
...oFile.write(uLine.encode("utf8")) # note this.
...sLine = iFile.readline()
iFile.close()
oFile.close()

Monday, May 29, 2006

Python note: get your ip address

Here is a small platform independent script for you to get the IP address for the current machine.

import socket
print socket.gethostbyname(socket.gethostname())

Sunday, May 28, 2006

Python note: SimpleHTTPServer note

Special notice for SimpleHTTPServer:

1. Read more of the source code! The SimpleHTTPRequestHandler is initialised, does the job and then dissappears. To retain it code must be edited.

2. Notice that each HTTP request asks only one response. This is HTTP protocol, and more responses will cause problems.

Tuesday, May 23, 2006

C++ note: references vs pointers

Use references when the target is a fixed object:

a_class* const a_inst=&a; => a_class &a_inst=a;

It's ideal to use references when passing a parameter to a function, because they probably won't move. However, when using references for return values we must be careful that the original value is in the heap and not in the stack (local varaible). It's more natural to return a pointer.

Use pointers in the cases of iterating through a lot of objects. Actually, iteration is probably the best place to use pointers. Also when the address is needed explicitly pointer is the only choice.

Saturday, May 13, 2006

VIM note: abbreviations

Command :abbr (:ab) sets abbreviations for strings. For example, with

:abbr #a hello

You could use #a[ENTER] in the INSERT mode to write "hello". This is useful for writing comment.

In my python files, I usually use comment blocks like

#--------------------------------------------
#
# Function header
#
#--------------------------------------------


This could neatly be done by putting some abbr commands to the .vimrc file

Note:
1. You must use # plus one letter for abbreviation names
2. Under windows the vimrc file is _vimrc, and you must make an environment variable VIM.

Wednesday, May 10, 2006

C++ note: virtual inheritance

The format

public class C: virtual B {...}

The main reason for virtual inheritance is for the diamond structure - B extends D, C extends D and A extends B, C. Without virtual mark, the instances of A will include data slots defined in both B and C, while the data slots defined in B and C will each include the data slots from D .

Python's will always have a diamond structure, because it always uses references. Of course Java does not have such problems.

Python note: when you get a lot of instances

Some classes has quite a lot of instances, and it's important to reduce the memory consumption by these objects. I blog two ways of doing it by Python.

First is using __slots__. Define this in the class definition, with a sequence type (normally tuple, but never string). For example,

class C(object):
...__slots__ = "foo", "bar"


This will make the instances of the class only have two attributes "foo" and "bar". Methods are the same, and they just need to be defined in the normal way.

The reason that __slots__ might save memory is that it saves the need of making a dictionary object in every instance to store possible attributes. This works when there are a large number of instances.

The second way is the flyweight pattern. The idea of this pattern is reusing existing objects.

For example, an email client maintains many messages. Each mail could be tagged with "read", "flag" etc. One client might contain huge number of email instances viewed at a time, and it's wise to reuse certain property instances for each email.

Lastly, my view regarding patterns is that they are not something to be enjoyed as programming tips. Different problems must be solved in different ways, and applying a pattern blindly is of no good. However, reading some patterns could give me hints in problem solving. And a byproduct is that I would know what people in the Java world are talking about ;-)

Wednesday, May 03, 2006

Python note: a file merger

Problem: I've got two folders, containing images from two Cannon camera. They were taken the same day. Unfortunately, these two cameras gave the same names to their pictures. I wanted to merge these two folders, with more powerful functionalities.

Script: This script takes in two folders, moving files from one folder to the other one. When there are duplicate file names, it compares the files. If the files are really duplicated, it only keeps one copy. If the files are different in content, they are renamed to different names by adding postfixes.

Code: The following python source
#
# merge files - merge two folders with no duplicate files
#
g_sWelcome = """
merge_files - merge files from two directories into one.

The files from the "from" directory will be moved to the "to" directory, while
duplicated files will be removed. If two files are in the same name but are
different in signature (revision time, size), the new one will be renamed.

Author: Yue Zhang, 2006
"""
import sys,os
import filecmp
import shutil
#
# Given a path, filename and extention, return a full path name without collision
#
def fileid_alloc(sPath, sPathFrom, sFileName, sExtension):
...global nDuplicateName, nDuplicateContent
...nIndex = 0
...sNewFileName = os.path.join(sPath, sFileName + sExtension)
...if os.path.exists(sNewFileName):
......nDuplicateName += 1
......if filecmp.cmp(sNewFileName, os.path.join(sPathFrom, sFileName + sExtension)):
.........nDuplicateContent += 1
.........return sNewFileName
...while os.path.exists(sNewFileName):
......nIndex += 1
......sNewFileName = os.path.join(sPath, sFileName + str(nIndex) + sExtension)
...return sNewFileName
#
# Main function
#
def merge_files(folder_from, folder_to):
...for sFullFileName in os.listdir(folder_from):
......sFileName, sExtension = os.path.splitext(sFullFileName)
......sNewFileName = fileid_alloc(folder_to, folder_from, sFileName, sExtension)
......shutil.move(os.path.join(folder_from, sFullFileName), sNewFileName)
#
# Main entry
#
if __name__ == '__main__':
...global nDuplicateName, nDuplicateContent
...nDuplicateName = 0
...nDuplicateContent = 0
...print g_sWelcome
...if len(sys.argv) != 3:
......print "Usage: merge_files.py folder_from folder_to"
......sys.exit(0)
...merge_files(sys.argv[1], sys.argv[2])
...print "In all %d duplicate file names processed, among which %d
............duplicate contents are merged and the rest are allocated new name."
............% (nDuplicateName, nDuplicateContent)

Disclaimer
: I give no warranty of responsibilities of use of the code, though I have tested this code with my own photos.

Sunday, April 30, 2006

VIM note: switch dos format to unix format

Still the same problem as my last Python note, now I want to do it with vim.

This could be done by global pattern replacement. The command is:
:%s/pattern/replacement

The pattern needs to use literal mode: [Ctrl-v] key
In this case it's [Ctrl-v][CR], showed as ^M. The whole command will look like :%s/^M$//.

Wednesday, April 26, 2006

Python note: SunOS file format switching

When I opened boost-jam src under SunOS, I found that each line was tailed with ^M. This is chr(13), which means that the end-of-line character for these files are \0xd\0xa.

To remove \0xd in the end-of-line character and switch files to format which SunOS reads, I wrote such a Python program.

import os
for sFile in os.listdir("."):
  os.system("sed 's/%s//g' %s>TEMP && mv TEMP %s"
  % (chr(13), sFile, sFile))


's/pattern/replace/g' is the general expression for string substitution with UNIX.

Tuesday, March 14, 2006

Python note: "?:" in Python

In C++ and Java there is a handy way of writing conditional expression, such as x = y>1?1:0. However there is no ?: operator in Python.

Several ways have been suggested around this problem. Some people use "a and b or c", while others use "(a and [b] or [c])[0]". However I don't think them intuitive.

I was using dict for the expression, and to express x = y>1 ? 1 : 0, I type

x = {True : 1, False : 0}[y>1]

which is also concise.

Wednesday, September 07, 2005

Python note: make use of built-in space

This is about the ways to make (cross module) global variables.

One way of sharing variables among runtime modules is defining a global module, and let every module import it. The global module will be loaded only once, because Python puts every loaded module into sys.modules and makes sure that it won't be executed again by import statements. Once the global module is loaded, every module could access global.xxx for variables. In this way the variables are shared as global.

The above method takes use of Python module loading mechanism to achieve global sharing. There is a more straightforward way. In Python, searching for variables follows the order of function -> module -> built-in scope. While the variable is not found anywhere in the module, the built-in scope will be looked for. This scope is defined as a global module (or dict).

Suppose we have main module:

main.py

g_nConfig = "blabla"
__builtins__.g_nConfig = g_nConfig

import first_module
import second_module

# other things to do

Then in the subsequent executions within the two imported modules, g_nConfig is accessible.

Now, suppose that there are many such global things to use. You can make a concentrated sharing for them. The easiest form could be a dict.

g_dGlobals = {'g_nConfig' : "bla bla", 'g_oObject1' : object1}

Of course, to make the global powerful, you can make it a class.

Friday, August 26, 2005

Python note: unicode

When you get some error output like this:

'ascii' encoding can not encode ...

The first thing to check is python unicode object.

Python chooses a separate type of object to support unicode, in order to keep string compatibility. Thus python has two kinds of strings: str and unicode. Str objects are the same as the standard C string - an array of chars. It is used in most function calls.

Each char in a computer system can represent 128 different values. For languages like English, the alphabet is below 30. Therefore we can find a mapping between each letter and each char value. Such a mapping is called encoding. ASCII is the most common encoding to map char values into letters.

For languages with many more than 128 letters, such as Chinese and Japanese, many chars need to be combined to represent one character. A problem arises. Because different languages have different interpretations of char values, the same string can be mapped into different letters / characters by different encodings. For example, when viewing one webpage, you can switch your browser to different encodings, and the page will be displayed differently (of course there is only one encoding that is 'correct') Unicode is proposed to solve the encoding clash, and it includes all possible characters / letters in languages. Interestingly, there are also many different UTF encoding versions, include utf-8, utf-16, etc.

Unicode objects in Python are actually strings encoded in utf-8. It can be seen as the abstract representation of the real character / letters, which can be encoded into different computer strings by different encodings. In other words, if strings are viewed as the outside form, Unicode can be viewed as the inside meaning.

Unicode objects can be changed to str object by the method 'encode'. It will translate the meaning to raw strings with certain encodings.

On the contrary, raw strings can be changed to unicode, using method 'decode'. When you know the 'correct' encoding of a raw string, you can tell it to the system and make it an unicode object.

There are methods to help you determine the os encoding. They are sys.getdefaultencoding() and sys.getfilesystemencoding(). Which are self explanatory.

Some methods in python work with str while other work with Unicode. You have no difficulty with those taking both types, but you need to be careful when calling a method that take only str or Unicode params. Also, the return type of a method us often neglected. For example, file.readline() would return a string. If a file is a unicode file, it's still a string encoded in 'utf-8'.

When a unicode object is passed to a method taking string params, or vice versa, the system will try to switch beween them automatically. However because we did not specify encodings beforehand, it will use ascii by default. When the real encoding can't be interpreted by the ascii char set, the exception at the beginning of this article will occur. The steps to take to fix the problem might be: first check the type of the string, using type() method, then try to convert it to the correct type by using encode() or decode, specifying the encoding.

Monday, August 22, 2005

wxPython note: process tab end enter key events for TextCtrl in dialogs

When you place a TextCtrl in a dialog and catch the Key events for it, you will find that enter and tab key events are not processed. When you press tab key, the focus will be switched to the next widget.

The solution is setting the style for the TextCtrl. There are two styles, wx.TE_PROCESS_ENTER and wx.TE_PROCESS_TAB, which default to unset. They will help in processing events.

Thursday, August 18, 2005

Haskell note: turorials

I am completely new to Haskell functional programming. I started to play with it simply because of the need in my MSc course. But it seems more and more interesting now.

Functional programming is quite different from "common", i.e. imperative programming, mainly in that it's not executed from the beginning to the end. A functional program can be taken as a set of equations, when calculated together yielding output.

I find this introduction succinct and helpful

http://www.haskell.org/tutorial/

Here are some good summary of the language.

About the grammar

http://www.cs.uu.nl/~afie/haskell/tourofsyntax.html

About the operators

http://www.imada.sdu.dk/~kornerup/DM22/Noter/haskell-operatorer.pdf

wxPython note: how to select many rows in Grid?

This problem puzzled me some time ago, and I forgot the solution again today. Thus I feel it necessary to take it down here.

There is absolutely no way of setting a style like wx.CB_MULTIPLE to specify multiple selection here. wxGrid support multiple row selection by itself, see a reference

http://lists.wxwidgets.org/archive/wx-dev/msg21759.html

The only thing you need to have is specifying the second (hidden!) param of SelectRow - bAppend (I am vague about the name). When it's true you will see the row selected without cleaning other rows.

Of course, this implies that selecting many rows can only be done from program. Thus in order to respond to mouse and keyboard behaviors, event catching and processing are needed. Anyway, it's not uncommon to process events for a grid.

Sunday, August 14, 2005

Introduction to MVC

Found a good introduction to the MVC pattern.

http://csis.pace.edu/~bergin/mvc/mvcgui.html

Also see a general explanation at

http://ootips.org/mvc-pattern.html