taglist是一個vim的class browser plugin,它能讓vim編寫程式更方便。
設定方式:
1. exuberant ctags 版本要在5.0以上
2. 下載taglist
3. 如果沒有建立過vim的plugin,要建立~/.vim,以及~/.vim/plugin這兩個目錄
4. 把taglist解壓縮,把裡面的 plugin/taglist.vim複製到 ~/.vim/plugin底下
5. 在.vimrc裡面加入 nnoremap <silent> <F8>
以上設定完畢,只要在進入vim時按F8,就能把這個檔案的class browse顯示在視窗左邊。
如果要一次開啟整個資料夾,也可以用以下的方法:
:TlistAddFilesRecursive /my/project/dir *.c
這樣就能一次把/my/project/dir 底下的所有.c檔匯入。
TlistAddFilesRecursive是把目錄底下的所有檔案以遞回方式全部載入,而TlistAddFiles則只載入這個目錄底下的檔案。
參考資料 :
Taglists plugin for Vim - http://bubudog.blogspot.com/2007/01/taglists-plugin-for-vim.html
2008年7月8日 星期二
| [+/-] |
[Vim] Class Browser : Taglist |
2008年7月1日 星期二
| [+/-] |
wxPython : 能改變顏色的文字編輯區塊StyledTextCtrl |
我們在編輯程式的編輯器中,顯示程式碼的區塊能根據不同語言的程式關鍵字而變色。
這樣的編輯區塊在wxPython裡面也有。
wx.stc.StyledTextCtrl:由Scintilla這個open source的編輯套件移植過來的,可以設定一些和編輯器相關的設定。
stc = wx.stc
stc.SetText(text) #設定string text到editor中
stc.SetKeyWords(keywordset, keywords) #設定editor的keyword
stc.SetCurrentPos(pos) #設定目前的位址
用這個元件我們就可以實作出屬於自己的editor。
參考資料 :
StyledTextCtrl - http://www.wxpython.org/docs/api/wx.stc.StyledTextCtrl-class.html
2008年6月27日 星期五
| [+/-] |
gdb的一些常用指令 |
backtrace(bt):顯示程式目前的stack狀態,用於檢查dump core很方便。
frame #:配合backtrace的結果,選擇要跳到的stack #,就可以檢查某個stack的狀態。
在多個source files裡面跳到其他file:list filename:1,用來跳到filename這個檔案的第一行。
用 list 也可以跳到某個檔案的某個function,list filename:function。
參考資料 :
http://www.study-area.org/cyril/opentools/opentools/x1253.html
| [+/-] |
Google App Engine |
如何利用Google App Engine來建立自己的Web Service:
http://blog.pixnet.net/jacklin0508/post/16272390
Google App Engine的 Tutorial:
http://code.google.com/appengine/docs/gettingstarted/
jQuery:Javascript Library
http://jquery.com/
django:Python Web Framework
http://www.djangoproject.com/
http://www.openfoundry.org/index.php?option=com_content&Itemid=144&id=1330&lang=en&task=view
參考資料 :
http://blog.pixnet.net/jacklin0508/post/16272390
2008年6月24日 星期二
| [+/-] |
[Python] 字串處理, 檔案讀取, 系統參數, Trace目錄 |
Python 字串處理:
return value
切token : str.split(delimiter) list
找字尾 : str.endswith(endString) bool (有沒有找到)
找字首: str.startswith(startString) bool (有沒有找到)
找子字串 : str.find(subString) 子字串的開頭位址
去空白 : str.strip() string
Regular expression:
re.search(regex, subject)
re.match(regex, subject)
re.findall(regex, subject)
re.finditer(regex, subject)
re.sub(regex, replacement, subject)
re.split(regex, subject)
re.complie(regex, subject)
檔案處理:
fp = open(file, "r") #讀檔
fileString = fp.read() #把整個檔案讀入buffer
fileLines = fp.readlines() #把整個檔案以一行一行形式讀入list
執行參數:
import sys
sys.argv #參數個數
sys.argv[1] #第1個參數
Trace 目錄:
import os, sys
from stat import *
def walktree(top, callback):
'''recursively descend the directory tree rooted at top,
calling the callback function for each regular file'''
for f in os.listdir(top):
pathname = os.path.join(top, f)
mode = os.stat(pathname)[ST_MODE]
if S_ISDIR(mode):
# It's a directory, recurse into it
walktree(pathname, callback)
elif S_ISREG(mode):
# It's a file, call the callback function
callback(pathname)
else:
# Unknown file type, print a message
print 'Skipping %s' % pathname
def visitfile(file):
print 'visiting', file
if __name__ == '__main__':
walktree(sys.argv[1], visitfile)
參考資料:
Python's re Module
stat -- Interpreting stat() results
Common string operations
Python Library Reference
2008年6月19日 星期四
| [+/-] |
Firefox 3.0 |
最新版本的Firefox比起之前的版本有以下的感覺:
1. 速度有變快
2. 附加元件管理員變的比較好
3. 書籤組織功能加強
Firefox一些好用的Plugins:
1. google toolbar:整合google的工具在 firefox 的 toolbar 上面。
2. GMark:專門使用 google 書籤 的 plugin,介面跟編輯有比原本 google toolbar 上面的好用,重點在於使用 Ubuntu 不會讓書籤無法下載。
3. RefControl:可以對某個網站指定要送的 Referer 是什麼,對於那種不讓站外連圖片的網站(無X),可以達到破解的效果。
4. Clipmarks:可以把一個網頁上的東西切成一塊一塊,並且選擇你想要剪下的部分,傳送到 Clipmarks 的網站。可以用來剪貼網路上面的資訊。
參考資料 :
Mozilla Taiwan 正體中文 - http://www.moztw.org/
2008年6月17日 星期二
| [+/-] |
wxPython中有興趣的widget |
顯示進度 (wx.Gauge):wxPython in Action(五十六)
顯示進度 Dialog (wx.ProgressDialog):wxPython in Action(七十七)
分割視窗 (wx.SplitterWindow) : wx.SplitterWindow
多重版面 (wx.Notebook):wx.Notebook
Wizard (安裝導覽, 教學導覽) (wx.Wizard):wxPython in Action(八十一)
參考資料 :
The wxPython tutorial - http://zetcode.com/wxpython/
wxPyhthon In Action - http://www.pythontik.com/blog/default.asp
2008年6月16日 星期一
| [+/-] |
C : 非固定參數function |
有很多格式化的function,像是 printf,scanf 之類,由於格式不固定,造成後面接的參數個數也不一定。這時候就要用到非固定參數 function 的技巧了。
#include <stdarg>
void print(char *fmt, ...)
{
//宣告一個多參數變數
va_list ap;
//重組的格式
char *nFmt;
//取得多參數變數的初始化
va_start(ap, fmt);
//重組字串的格式 (asprintf 會自動幫buf allocate記憶體)
asprintf(&nFmt, "%s\n", fmt);
//輸出結果到stdout
vfprintf(stdout, nFmt, ap);
//釋放asprintf 自動 allocate的記憶體
free(nFmt);
}
這個function print所做的事情就是把原本要印出的字串格式重組,
最後在後面加個"\n"。
參考資料 :
man va_start
2008年6月13日 星期五
| [+/-] |
libpq : include 和 library 的設定 |
在 shell 下輸入:pg_config --help ,會出現很多 option 可以選擇。
其中 --includedir 是 libpq C header的位置
而 --libdir 是 library的位置
在compile時,把 gcc -I (include dir) 和 -L (library dir) 的 path 設定正確,這樣才不會出現 undeclare 或是 undefined reference 的錯誤產生
參考資料 :
http://www.freebsd.org.hk/html/postgresql/libpq-chapter.htm
| [+/-] |
libpq : 存取PostgreSQL的C API |
我們寫的程式透過 libpq 的 api 可以間接存取 PostgreSQL 裡面的資料。
要對 PostgreSQL 執行一個 SQL Command 步驟分成以下幾步:
1. 連上 PostgreSQL 上的 DB ( conn = PQconnectdb(connStr) )
2. 檢查 PQconnectdb 回傳的狀態 ( PQstatus(conn) == CONNECTION_OK )
3. 執行 SQL Command ( res = PQexec(conn, SQLCmd) )
4. 檢查回傳的 res 是否正常 ( PQresultStatus(res) == PGRES_TUPLES_OK )
5. 取出 res 裡的資料 ( for (i = 0; i < PQntuples(res); i++)
{
PQgetvalue(res, i, 0)
}
)
6. 清除資料 ( PQclear(res) )
7. 和資料庫斷線 (PQfinish(conn))
參考資料 :
C Language Interface (LIBPQ) - http://www.postgresql.org/files/documentation/books/aw_pgsql/node147.html
2008年6月12日 星期四
| [+/-] |
C++ : 如何把class member function當成function pointer傳入 |
將 member function 宣告成 static 就可以傳入。
可是 static member function 不能呼叫this pointer,這樣就失去呼叫 member function 的意義了。解決方法是把在呼叫時,把物件的指標傳入。但是呼叫別人的function時,不能改變參數,所以必須建立一個 global variable 或是 static member variable ,在產生物件的同時,把這個變數設定成物件的 reference ,這樣一來呼叫 static member function 時,就可以利用這個 variable 來呼叫物件的其他東西。
class Obj
{
public:
static void *self; //指向自己的pointer
Obj()
{
Obj::self = this; //指向自己
}
static void WrapperFun() //wrapper function
{
Obj::self->Fun(); //真正要呼叫的member function
}
void Fun()
{
//...
}
};
呼叫時:
some_function(WrapperFun);
這樣就可以達到呼叫我們要呼叫的non-static member function的效果了。
參考資料 :
Executing an Object's Member Function in a Separate Thread - http://gethelp.devx.com/techtips/cpp_pro/10min/10min0800.asp
How to use SetTimer() with callback to a non-static member function - http://www.cppblog.com/leo-chen/archive/2007/05/16/24186.html
2008年6月10日 星期二
| [+/-] |
vim我會用的指令 |
在unix上編輯東西當然少不了vim。雖然沒有視窗的直覺化,但是透過簡潔的指令,我們更能專注於我們要編輯的內容,而不是隨意的剪剪貼貼。
下面介紹編輯檔案好用的多檔編輯:
1. 開啟檔案時可以 vim file1 file2 ... 一次開啟好多檔案。
2. 輸入 :files 會出現檔案名稱以及檔案編號。
3. :n 可以編輯下一個檔案
4. :N 可以編輯上一個檔案
5. :b# #代表輸入 :files 以後出現的檔案前面的編號,用來跳到編號為#的檔案編輯。
6. 按 Ctrl + ^ ,可以切換目前檔案以及前一個編輯的檔案。
透過這些指令在多個檔案的編輯也可以很簡單達成。
其他詳細的 vim 介紹,可以到鳥哥的 Linux 私房菜 - vi 文書處理器或是大家來學 Vim 一個歷久彌新的編輯器找到詳細內容。
參考資料 :
鳥哥的 Linux 私房菜 - vi 文書處理器 - http://linux.vbird.org/linux_basic/0310vi.php
大家來學 Vim 一個歷久彌新的編輯器 - http://edt1023.sayya.org/vim/
2008年6月9日 星期一
| [+/-] |
Unix Socket程式範例 |
Server :
建立socket -> 設定local address -> 將socket bind在local port上 -> listen client socket -> 當有socket連線時accept client socket -> recv/send
Client :
建立socket -> 設定remote(server) address -> connect遠端server -> 當connect成功之後 -> recv/send
範例請見參考資料。
參考資料 :
http://www.pcs.cnu.edu/~dgame/sockets/sockets.html
2008年6月5日 星期四
| [+/-] |
read function 設定Non-Blocking I/O的方式 |
利用 fcntl 或是 ioctl 來設定 Non-Blocking I/O,讓 read function 不會被 Block住:
#include <fcntl.h> //fcntl的header
#include <sys/ioctl.h> //ioctl的header
...
int flag;
//用fcntl設定Non-Blocking I/O
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
//用ioctl設定Non-Blocking I/O
ioctl(STDIN_FILENO, FIONBIO, &flag);
fcntl的完整用法是先用F_GETFL取得flags,在把flags和要改變的flag進行&、|,最後在用F_SETFL把flags設定回去。
int flags;
//取得flags
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
{
//進行錯誤處理
}
//加入non-blocking I/O的flag
flags |= O_NONBLOCK;
//設定flags
if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
{
//進行錯誤處理
}
參考資料 :
Advanced Programming in the Unix Environment
| [+/-] |
C程式在Unix下取得時間 |
在Unix下取得時間的方法如下:
1. time取得系統時間 (time_t)
2. 把 time_t 的時間轉換成 struct tm 格式的時間:localtime (取得在地時間),gmtime (取得格林威治時間)
3. 用印出 struct tm 的函式來把時間用想要的格式印出:asctime (預設的格式),strftime (可以自訂輸出格式)
以上就是轉換流程,如果要把 struct tm 轉回 time_t 則是用 mktime 。
#include <time.h>
...
time_t t;
struct tm *tm_t;
//取得系統時間
t = time(NULL);
//把系統時間轉成當地時間
tm_t = localtime(&t);
//印出時間
printf("%s", asctime(tm_t));
//把strcut tm轉成time_t
//t = mktime(tm_t);
參考資料 :
http://www.cs.nctu.edu.tw/~yslin/library/linuxc/function/04.html
Standard C Date & Time - http://www.cppreference.com/stddate/index.html
| [+/-] |
關於匈牙利命名法的討論 |
進入公司後看到的 Code 大部分都是用 匈牙利命名法 這個規則命名的。一開始的時候看到變數前面有m_、n、sz、lp等等一連串的怪怪 prefix ,讓本來就不懂的程式碼看起來更加痛苦。但是慢慢的了解了這個規則以後,發現到看別人的程式,如果有這樣的命名其實還不錯。
像是大家常常喜歡執行一個 Member Function 來改變 Member Variables ,當然程式如果是自己寫的很容易就知道那些 Member Variables 被修改了。但是這可苦了看你程式的人,尤其是沒有寫 Function 註解的時候。往往一個 Member Function 做完了以後,沒有回傳值,根本不曉得它到底做了些什麼。
所以說 匈牙利命名法 真的這麼好嗎?
在網路上搜尋的結果,發現到當然也是有人覺得它不錯,但是下面這篇討論,指出了它受到質疑的缺點 : 匈牙利命名法討論的文章。
當然缺點裡面有誇大的地方,不見得所有的地方都是不好的。Making Wrong Code Look Wrong(中文)這篇文章,就指出了 匈牙利命名法 最初的原意。它的用途在於知道變數的種類(Kind),而不是型態(Type)。知道變數的種類(Kind)就能幫助看程式的人,從變數本身看出程式碼的錯誤。文章裡面也有舉了一個例子來說明。
所以當你使用 匈牙利命名法 來命名的時候,可以想想看這樣的做法是否可以幫助你了解程式,以及對程式的除錯是否有幫助。不然這樣的做法會讓程式的變數看起來眼花撩亂,可能跟你原本想要的結果大有不同 (最終目的是幫助程式的閱讀)。
參考資料 :發佈文章
Making Wrong Code Look Wrong(英文) - http://www.joelonsoftware.com/articles/Wrong.html
Making Wrong Code Look Wrong(中文) - http://chinesetrad.joelonsoftware.com/Articles/Wrong.html
匈牙利命名法討論的文章 - http://tsjeremy.spaces.live.com/blog/cns!BD4EB7F462639B16!1346.entry
| [+/-] |
程式碼的風格 (Coding Style) |
寫了這麼久的程式,但是對 Coding Style 卻沒有一個很明確的規範。常常變數寫怎麼取就怎麼取,因為以前寫的程式都是為了單一的目的 (通常是交作業) 而寫的。在進公司接了別人的程式以後,就深深的覺得好的 Coding Style 真的很重要。
像是變數的命名方式,如果在取名的時候不在 Class Member 前面加上 m_ 的前置符號,在看新的程式就會很難判別一個變數的範圍。往往在一個 Function 執行完以後,還不知道這個 Function到底做了些什麼事情,因為不曉得哪些變數是 Class Member 。帶大量參數的縮排也是一樣,好的縮排可以幫助我們很快的了解這個 Function 裡面的參數意義。當然我覺得最重要的還是在 Function 或是 Class 的前面可以加上註解會是更好的,常常你的小小註解,可以省下其他人 (更常是自己)很多時間。
下面這三份資料是介紹一些 Coding Style 的方法,分別是 C , C++ , C# 。但是我想基本概念都是差不多的。
C♯ Coding Style Guide
C++ Programming Style Guidelines
Recommended C Style and Coding Standards
希望大家的程式碼都是能容易閱讀的,讓看別人的程式碼變成是程式技術增進的快速方法,而不是一個痛苦的工作。
參考資料 :
C♯ Coding Style Guide - http://www.icsharpcode.net/TechNotes/SharpDevelopCodingStyle03.pdf
C++ Programming Style Guidelines - http://geosoft.no/development/cppstyle.html
Recommended C Style and Coding Standards - http://www.psgd.org/paul/docs/cstyle/cstyle.htm
2008年6月4日 星期三
| [+/-] |
Bsd裡面的ls顏色設定 |
設定的流程如下 :
1. 設定TERM這個環境變數為xterm-color (在openbsd裡面為xterm-color)
2. 確認 ls 產生顏色的方法。是用 ls --color 來設定,還是用 colorls -G 。
3. 在 .profile 檔裡面 (ksh) ,設定 alias 方便使用。例如:alias ls = 'colorls -G'
4. 更改顏色的設定,在bsd裡面是用LSCOLORS這個變數的設定
DIR=Dx
SYM_LINK=Gx
SOCKET=Fx
PIPE=dx
EXE=Cx
BLOCK_SP=Dx
CHAR_SP=Dx
EXE_SUID=hb
EXE_GUID=ad
DIR_STICKY=Ex
DIR_WO_STICKY=Ex
export LSCOLORS="$DIR$SYM_LINK$SOCKET$PIPE$EXE$BLOCK_SP$CHAR_SP
$EXE_SUID$EXE_GUID$DIR_STICKY$DIR_WO_STICKY"
上面的LSCOLORS後面的內容為一行。
詳細的介紹可以參考ls 顏色設定(in Bash shell)。
參考資料 :
ls 顏色設定(in Bash shell) - http://plog.longwin.com.tw/post/1/408
| [+/-] |
使用CAsyncSocket碰到的問題 : Create |
在用MFC寫網路程式的時候,會用CAsyncSocket來產生出自己的非同步Socket Class。用CAsyncSocket建立連線的時候,Client端只要呼叫Create和Connect這兩個Function就好了,不需要像純粹的Socket一堆設定動作。
而這些繁雜的設定都被包在Create裡面了,這也是我這次碰到的問題。
那Create裡面到底做了些什麼?
1. 呼叫CAsyncSocket的Socket函式
1.1 Socket函式裡面會先檢查m_hSocket是否被清成INVALID_SOCKET
1.2 呼叫利用socket函式產生新的m_hSocket
2. 如果呼叫Socket函式成功,接下來呼叫Bind函式,在Bind函式裡面會設定一些Socket相關資訊,然後進行Bind的動作
3. 最後就是成功Create,然後執行Connect到Server。
而我產生錯誤的地方就在 1.1 的部分,因為我的程式可能因為遠端Server無法連線而造成Connect失敗,在Connect失敗以後我沒有呼叫Close來清除m_hSocket的資源,並且將m_hSocket給設定成INVALID_SOCKET,因此在呼叫Create的時候就會產生出ASSERT的錯誤訊息。
所以對於使用的函式庫的function,如果能多了解裡面程式碼實際的內容的話,就能避免掉一些因為和函式庫設計邏輯不同而產生的錯誤。
參考資料 :
MSDN