2009年11月8日 星期日

C 語言新手十誡

C 語言新手十誡(The Ten Commandments for Newbie C Programmers)

by Khoguan Phuann
請注意:

(1) 本篇旨在提醒新手,避免初學常犯的錯誤(其實老手也常犯:-Q)。
但不能取代完整的學習,請自己好好研讀一兩本 C 語言的好書,
並多多實作練習。

(2) 強烈建議新手先看過此文再發問,你的問題極可能此文已經提出並
解答了。

(3) 以下所舉的錯誤例子如果在你的電腦上印出和正確例子相同的結果,
那只是不足為恃的一時僥倖。

(4) 不守十誡者,輕則執行結果的輸出數據錯誤,或是程式當掉,重則
引爆核彈、毀滅地球(如果你的 C 程式是用來控制核彈發射器的話)。


一、你不可以使用尚未給予適當初值的變數。


錯誤例子:
int accumulate(int max) /* 從 1 累加到 max,傳回結果 */
{
int sum; /* 未給予初值的區域變數,其內容值是垃圾 */
int num;
for (num = 1; num <= max; num++) {
sum += num;
}
return sum;
}

正確例子:
int accumulate(int max)
{
int sum = 0; /* 正確的賦予適當的初值 */
int num;
for (num = 1; num <= max; num++) {
sum += num;
}
return sum;
}

二、你不可以存取超過陣列既定範圍的空間。

錯誤例子:
int str[5];
int i;
for (i = 0; i <= 5; i++) str[i] = i;

正確例子:
int str[5];
int i;
for (i = 0; i < 5; i++) str[i] = i;

說明:宣告陣列時,所給的陣列元素個數值如果是 N, 那麼我們在後面
透過 [索引值] 存取其元素時,所能使用的索引值範圍是從 0 到 N-1,
也就是 C 和 C++ 的陣列元素是從第 0 個開始算起,最後一個元素的
索引值是 N-1, 不是 N。

C/C++ 為了執行效率,並不會自動檢查陣列索引值是否超過陣列邊界,
我們要自己寫程式來確保不會越界。一旦越界,將導致無法預期的後果。

三、你不可以提取(dereference)不知指向何方的指標(包含 null 指標)。

錯誤例子:
char *pc1; /* 未給予初值,不知指向何方 */
char *pc2 = 0; /* pc2 起始化為 null pointer */
*pc1 = 'a'; /* 將 'a' 寫到不知何方,錯誤 */
*pc2 = 'b'; /* 將 'b' 寫到「位址0」,錯誤 */

正確例子:
char c; /* c 的內容尚未起始化 */
char *pc1 = &c; /* pc1 指向字元變數 c */

/* 動態分配 10 個 char(其值未定),並將第一個char的位址賦值給 pc2 */
char *pc2 = (char *)malloc(10);
*pc1 = 'a'; /* c 的內容變為 'a' */
pc2[0] = 'b'; /* 動態配置來的第 0 個字元,內容變為 'b'
/* 最後記得 free() 掉 malloc() 所分配的空間 */
free(pc2);

說明:指標變數必需先指向某個明確的東西(object),才能進行操作。

四、你不可以將字串常數賦值(assign)給 char* 變數,然後透過該變數
改寫字串的內容(只能讀不能寫)。

錯誤例子:
char* pc = "john";
*pc = 'J';
printf("Hello, %s\n", pc);

正確例子:
char pc[] = "john";
*pc = 'J'; /* 或 pc[0] = 'J'; */
printf("Hello, %s\n", pc);

說明:字串常數的內容是唯讀的。上面的錯誤例子,是將其內容所在的位址賦
值給字元指標 pc, 我們透過指標只可以去讀該字串常數的內容,而不應該做
寫入的動作。而正確例子,則是另外宣告一個獨立的字元陣列,它的大小我們
未明文指定([]),編譯器會自動將其設為剛好可以容納後面的字串常數起始
值的大小,包括字串後面隱含的 '\0' 字元,並將字串常數的內容複製到字元
陣列中,因此可以自由的對該字元陣列的內容進行讀和寫。

錯誤例子(2):
char *s1 = "Hello, ";
char *s2 = "world!";
/* strcat() 不會另行配置空間,只會將資料附加到 s1 所指唯讀字串的後面,
造成寫入到程式無權碰觸的記憶體空間 */
char *s3 = strcat(s1, s2);

正確例子(2):
/* s1 宣告成陣列,並保留足夠空間存放後續要附加的內容 */
char s1[20] = "Hello, ";
char *s2 = "world!";
/* 因為 strcat() 的返回值等於第一個參數值,所以 s3 就不需要了 */
strcat(s1, s2);

五、你不可以對尚未分配所指空間的 char* 變數,進行(字串)陣列的相關操作。
其他型別的指標亦然。

錯誤例子:
char *name; /* name 尚未指向有效的空間 */
printf("Your name, please: ");
gets(name);
printf("Hello, %s\n", name);

正確例子(1):
/* 如果編譯期就能決定字串的最大空間,那就不要宣告成 char* 改用 char[] */
char name[21]; /* 字串最長 20 個字元,另加一個 '\0' */
printf("Your name, please: ");
gets(name);
printf("Hello, %s\n", name);

正確例子(2):
/* 若是在執行時期才能決定字串的最大空間,則需利用 malloc() 函式來動態
分配空間 */

size_t length;
char *name;
printf("請輸入字串的最大長度(含null字元): ");
scanf("%u", &length);
name = (char *)malloc(length);
printf("Your name, please: ");
scanf("%s", name);
printf("Hello, %s\n", name);
/* 最後記得 free() 掉 malloc() 所分配的空間 */
free(name);

注意:上例用 gets() 或 scanf() 來讀入字串,是不安全的。 因為這些函式
不會幫我們檢查使用者所輸入的字串長度是否超過我們所分配的 buffer 空間,
很可能會發生 buffer overflow。比較安全的做法是用 fgets() 來取代。如:

char *p;
char name[21];
printf("Your name, please: ");
fgets(name, sizeof(name), stdin);
/* fgets()會連行末的'\n'也讀進字串中,所以要找出存入'\n'的位置,填入 '\0'
if ((p = strchr(name, '\n')) != NULL)
*p = '\0';
printf("Hello, %s\n", name);

六、你不可以在函式中回傳一個指向區域性自動變數的指標。否則,會得到垃圾值。
[感謝 gocpp 網友提供程式例子]

錯誤例子:
char *getstr(char *name)
{
char buf[30] = "hello, "; /*將字串常數"hello, "的內容複製到buf陣列*/
strcat(buf, name);
return buf;
}

說明:區域性自動變數,將會在離開該區域時(本例中就是從getstr函式返回時)
被消滅,因此呼叫端得到的指標所指的字串內容就失效了。【不過,倒是可以從
函式中直接傳回字串常數,賦值給呼叫端的一個 const char * 變數,它既是唯
讀的(參見第四誡),同時也具有恒常的儲存期(static storage duration),其
內容將一直有效。】

正確例子:
void getstr(char buf[], int buflen, char const *name)
{
char const s[] = "hello, ";
assert(strlen(s) + strlen(name) < buflen);

strcpy(buf, s);
strcat(buf, name);
}

[針對字串操作,C++提供了更方便安全的 string class, 能用就盡量用]
#include
using std::string;

string getstr(string const &name)
{
return string("hello, ") += name;
}

七、你不可以只做 malloc(), 而不做相應的 free(). 否則會造成記憶體漏失。

但若不是用 malloc() 所得到的記憶體,則不可以 free()。已經 free()了
所指記憶體的指標,在它指向另一塊有效的動態分配得來的空間之前,不可
以再被 free(),也不可以提取(dereference)這個指標。

[C++] 你不可以只做 new, 而不做相應的 delete.

八、你不可以在數值運算、賦值或比較中隨意混用不同型別的數值,而不謹慎考
慮數值型別轉換可能帶來的「意外驚喜」(錯愕)。必須隨時注意數值運算
的結果,其範圍是否會超出變數的型別。


錯誤例子(1):
unsigned int sum = 2000000000 + 2000000000; /* 20 億 */
double f = 10 / 3;

正確例子(1):
/* 全部都用 unsigned int, 注意數字後面的 u, 大寫 U 也成 */
unsigned int sum = 2000000000u + 2000000000u;

/* 或是用顯式的轉型 */
unsigned int sum = (unsigned int)2000000000 + 2000000000;

double f = 10.0 / 3.0;

說明:在目前最普遍的32位元PC作業平台上,整數常數2000000000的型別為
signed int(簡寫為 int),相加後,其結果仍為 int, 但是 signed int
放不下 4000000000, 造成算術溢位(arithmetic overflow),很可能無法
將正確的值指派給 unsigned int sum,縱使 unsigned int 放得下4000000000
的數值。注意:寫成

unsigned int sum = (unsigned int)(2000000000 + 2000000000);

也是不對的。

例子(2):(感謝 sekya 網友提供)
unsigned char a = 0x80;
char b = 0x80; /* implementation-defined result */
if( a == 0x80 ) { /* 恒真 */
printf( "a ok\n" );
if( b == 0x80 ) { /* 不一定恒真 */
printf( "b ok\n" );
}

說明:在將 char 型別定義為範圍從 -128 至 +127 的系統上,int 0x80
(其值等於 +128)要轉成 char 會放不下,會產生編譯器自行定義的值。
這樣的程式就不具可移植性了。

九、你不可以在一個運算式(expression)中,對一個基本型態的變數修改其值
超過一次以上。否則,將導致未定義的行為(undefined behavior)。


錯誤例子:
int i = 7;
int j = ++i + i++;

正確例子:
int i = 7;
int j = ++i;
j += i++;

你也不可以在一個運算式(expression)中,對一個基本型態的變數修改其值,
而且還在同一個式子的其他地方為了其他目的而存取該變數的值。(其他目的,
是指不是為了計算這個變數的新值的目的)。否則,將導致未定義的行為。

錯誤例子:
int arr[5];
int i = 0;
arr[i] = i++;

正確例子:
int arr[5];
int i = 0;
arr[i] = i;
i++;

[C++程式]
錯誤例子:
int i = 10;
cout << i << "==" << i++;

正確例子:
int i = 10;
cout << i << "==";
cout << i++;

十、你不可以在macro的定義中,不為它的參數個別加上括號。

錯誤例子:
#include
#define SQUARE(x) (x * x)
int main()
{
printf("%d\n", SQUARE(10-5));
return 0;
}

正確例子:
#include
#define SQUARE(x) ((x) * (x))
int main()
{
printf("%d\n", SQUARE(10-5));
return 0;
}

說明:如果是用 C++, 請多多利用 inline function 來取代上述的 macro,
以免除 macro 定義的種種危險性。如:

inline int square(int x) { return x * x; }

macro 定義出的「偽函式」至少缺乏下列數項函式本有的能力:

(1) 無法進行參數型別的檢查。
(2) 無法遞迴呼叫。
(3) 無法用 & 加在 macro name 之前,取得函式位址。
(4) 呼叫時往往不能使用具有 side effect 的引數。例如:

錯誤例子:(感謝 yaca 網友提供)
#define MACRO(x) (((x) * (x)) - ((x) * (x)))
int main()
{
int x = 3;
printf("%d\n", MACRO(++x));
return 0;
}

MACRO(++x) 展開來後變成 (((++x) * (++x)) - ((++x) * (++x)))
違反了第九誡。在 gcc 4.3.3 下的結果是 -24, 在 vc++ 下是 0.


後記:從「古時候」流傳下來一篇文章

"The Ten Commandments for C Programmers"(Annotated Edition)
by Henry Spencer
http://www.lysator.liu.se/c/ten-commandments.html

一方面它不是針對 C 的初學者,一方面它特意模仿中古英文
聖經的用語,寫得文謅謅。所以我現在另外寫了這篇,希望
能涵蓋最重要的觀念以及初學甚至老手最易犯的錯誤。

作者:潘科元(Khoguan Phuann) (c)2005. 感謝 ptt.cc BBS 的 C_and_CPP
看板眾多網友提供寶貴意見及程式實例。

2009年8月12日 星期三

學歷?能力?

爸媽都是工人出生,他們從很年輕時就必須出外工作賺錢幫忙維持家計。小時候, 他們在讀書方面表現不錯,只因家境貧困,而無法就讀初中。因此,在他們心裏 面,就希望我們好好用功讀書,將來不用像他們一樣賺錢辛苦。話雖如此,但他們還是以興趣為導向,而不會硬逼或強逼我們一定要考第一名,或升學上什麼很利害 的學校。也因為這樣,我們在讀書上就真的是以"興趣"為導向。...(爸媽到目前都還不知道,我國中曾因某件事對國文老師不爽,而交了近一年白卷...有 叛逆吧><)
在自己的決定之下,利用助學貸款完成研究所學業。對大學及研究所的印象只有二件事...."讀書"及"交女朋友"(目前 的老婆)。也許是考插大所養成的讀書習慣以及室友們也是很會讀書的怪咖(當時三個室友,二個室友博士畢業,另一個室友在美國攻博士)。很難想像,當同學們 去聯誼、去玩社團到處趴趴走時,我們幾乎每天晚上七點到系上圖書館報到,十點或十一點回宿舍休息,就算假日沒回家,也是窩在圖書館裏找顏如玉。這樣的日 子,在當時覺得很平常。(也許很多人覺得我們瘋了)
之後,交了很不錯的女朋友,去申請國防役,結果就順利在目前的單位上班了。然而,一晃眼就是七 八年過去。現在,自己有了二個小孩,常常也會思考他們的教育問題。我老婆是一直很想塞"知識"給小孩子,而我反而覺得知識是其次,重要的是品德、生活常規 及處理事情的態度。 目前台灣社會上,擁有研究所學歷的人非常多,有博士學位的人也很多。博士、研究生、大學生三者的差別在哪?相信有超過五成的所謂高知識分子無法回答。就算 無法回答也是照樣可以讀研究所或博士班。但這其實讓我很憂心台灣在高等教育及一般教育上的能力差異化。也就是說,政府沒有一個明確的機構或單位可以協助這 些欲升學的學生們進行升學性向分析及升學就業分析諮詢,而造就目前不少已經讀到博士或碩士的人不知為何而讀書?畢業後,也不知道能做什麼工作?或者是勉強 撐畢業了,但學業基礎實力太低,空有高學歷,而在社會上找工作仍處處碰壁的情形。最近,身旁不少人打算升學,希望她(他)們能了解所為何事。若知其事就認 真去讀,而不是"研究所學歷比較好看,比較好找工作...等"之粗淺且表面的理由。畢境,怎麼收穫就怎麼栽。

2009年8月11日 星期二

Windows XPE 之 EWF功能指令

Windows XPE 之 EWF功能指令

啟動EWF: ewfmgr C: -enable

解除EWF: ewfmgr C: -commitanddisable

2009年8月6日 星期四

SVN 資料庫格式太舊問題

幾年來,我習慣把工作上的文件檔案與程式檔案都用SVN來管理,而且只要一段時間把SVN資料庫備分即可。但最近公司電腦掛了,而我也換了4核心的新電腦。今天早上,想要把工作檔案更新到資料庫上(Commit)時,發現出現Failed to load module for FS type 'bdb'這樣的錯誤訊息,而不給Commit。
Google了一下,發現原來這是資料庫新舊的問題。只要dump出來,再重新create新的資料庫,然後再load進去就可以了。
找到的資料如下。(為了尊重原作,我一個字都沒改XD)


Failed to load module for FS type ‘bdb’ in TortoiseSVN 1.6.x

May 15th, 2009 by Robert

Today I’ve met small problem with my beloved TortoiseSVN client. I was in need to access some old repository stored locally on my computer – for newer projects I’m usingdedicated Debian based SVN server. Anyway, trying to access to my local repository via TortoiseSVN has resulted with following message:

Failed to load module for FS type 'bdb'

After quick Googling it appeared that from branch 1.6.x, TortoiseSVN doesn’t support local file:/// repositories based on BDB and they need to be converted to new FSFS format using ’svnadmin’ command line tool as it is explained in SVNBook. As ’svnadmin’ tool is not present in TortoiseSVN, some additional work is needed.

Finally I did in following way:

1. download and Tigris build of SVN (it was svn-win32-1.6.1.zip in my case). I’ve tried both 1.5.x and 1.6.x version of CollabNet’s SVN but apparently they do not support local BDB as well,
2. unpack it to any directory, and using command line enter to the bin subdirectory where the svnadmin.exe tool is stored
3. as written in the book, make dump of your repository with following command:

svnadmin dump c:\FullPathToOldRepository > dumpfile.bin

4. create new repository in choosen directory, you can use TorotoiseSVN for it as well, now it won’t ask you for data storage format as BDB is disabled, so it will use FSFS.
5. import dump data into new repository:

svnadmin load c:\FullPathToNewRepository < dumpfile.bin

That is, it worked for me like a charm.

2009年7月23日 星期四

98快樂撞撞賽

7/23晚上是公司撞球社的年度比賽。原本沒有足夠經費可以舉辦,但是靠著社長及快委會主委的努力爭取,終於感動組長,讓組長願意撥下經費舉辦這個比賽活動。
今年大約有18人參賽,約20多人到場加油助陣。因此,比賽的活動盛況比去年度還要盛大。當然除了大家對撞球社的支持之外,更重要的是社長的努力經營感動大家,這也讓我這前社長感到十分安慰。
比賽開始前,主委及社長準備了好吃的大G排、好喝的飲料以及有名的鹽水G,幫大家填飽肚子。接著開始雙敗洮汰的比賽了。
這次多虧了老婆大人的體貼支持,獨自對付二個小孩,才能讓我如期參加比賽。這回,總共打了七場(小仙-->X銘-->老洪-->小仙 -->X銘-->小胖-->志明),最後很幸運得到九號球比賽亞軍。名次我早就置之度外,重要的是能快樂跟同事們打球啊XD。
這種比賽的fu很讚,沒有緊張廝殺的感覺,只有快樂撞球的氣氛;跟之前去新竹比賽的感覺簡直天壤之別。
總之,感謝主委及社長讓我在這麼黑皮情境下比賽撞球,並且...............拿到獎金囉。哈!


2009年7月15日 星期三

2009 通訊大賽-健康小鈴

Google於去年推出Android作業系統,主要是應用於手持式或嵌入式系統上。於六月多在一個偶然的機會見到此課程在公 司的教育訓練網中出現,當時以為本課程是以介紹作業系統及porting為主,想藉此了解一下Android OS是否有機會在CNC控制器上實現。因為許多產業機械控制器功能簡單,也許有機會將人機介面及運動控制核心以Android OS來實現以降低成本。但是報名參加課程之後才發現,這是堂Android AP的簡介課程,跟我原先想的課程內容差異十分大,不過即然花了錢報名,就好好聽下去了。
這是為期二天的課程,第一天課程結束之後,我對 Android AP的設計有了很初步的認識。(畢境我不會Java,也不會XML)但第二天的課程由於公司有很重要的SBIR說明會,長官指示要代表部門說明部門核心技 術,因此無法出席。(這要對YSL老師說聲報歉,我不是故意要翹課啊 )
幾天後,我因好奇上網看到HTC新出品的Magic手機,讓我又開始對Android AP的設計產生興趣。於是,把老師上課的範例自己實作一次,也得到小小的成就感。
6/19, 在網路上無意中發現經濟部辦了一個2009通訊大賽,內容是Android AP的程式設計比賽。我順口開玩笑問太太,參加這個好嗎?結果她就說"好啊!參加看看啊!"看了參賽的相關規定、作品繳交時間、還要拍說明影片而且還要寫 程式說明書。心裏只有一個想法"哇賽!真是個挑戰啊。"
6/20晚上看MSN List發現,有個朋友很會繪圖,也許可以邀她一塊組隊參加,沒想到她一口答應,這下讓我也非得參加比賽了。(如果她不參加,那我至少還有藉口不參加)
於是約好6/22下班討論相關事宜,後來因為6/21小孩出生就延到6/24下班才討論。因為畢竟這算是私事,該公私分明。
見了面之後,開始說明這次比賽的相關事項並與LYC(我的參賽伙伴)討論我所想寫的程式主題及想法。而她也十分有興趣熱烈討論著,中間經過三次面對面的討論並且幾天晚上一塊線上熬夜以MSN溝通修改總算將畫面的圖片全部設計完成。
而對我來說Java語言與XML從未學習過,靠著有C++及C#的基礎,程式邊寫邊翻書邊學,也把健康小鈴(參賽的程式名稱)的程式部分完成。雖說完成, 但其實離我的標準還是有段距離。只因參賽的時間有限,只好先將功能面盡量做出來,盡量以一個完整的程式參賽。
這 些日子,女兒出生,我也陪老婆在月子中心住了近一個月。幾乎晚上除了抱抱小孩以及幫老婆處理一些雜務之外,就是在我的蘋果前面寫程式。而且,這些日子幾乎 沒有一天是睡飽的。終於在7/10感冒了。月子中心知道我感冒之後,如臨大敵似將我請出月子中心,而我也只好把電腦及相關東西帶回並搬回家住。這幾天,我 還是沒有乖乖的休息,每天寫程式搞到半夜二三點,終於程式在7/12的半夜完工了。
7/13離送件只剩二天。但是還有二件事沒完成,拍程式簡介說明影片及撰寫程式說明書。這天,我一個人在書房電腦前,大約錄了三次,就把程式說明影片給錄完了。(可能平常嘴皮子有在練,只NG二次算快的了XD)
7/14晚上,我開始撰寫程式說明書。雖說撰寫文件也算是我的強項之一,但也夯不啷噹的寫到半夜二點多了。這時,我就把程式、說明影片及程式說明書上傳。總算完成這次2009通訊大賽的交件了。
回想這次參賽的過程,除了感謝老婆的支持之外,就是我的伙伴LYC了。她花了不少時間及精神在美工設計上,並且也好幾天跟我線上熬夜討論。說真的,她在美工的天份及熱情真令我刮目相看。(感覺我們兩個都是瘋子~~~)
對我來說,這次參賽不論是否得獎,重要的是,我完成了一件想做但看似不可能的事(決定參賽時只剩三個星期,要用到的程式語言Java及XML都沒學過,並 且 Android AP設計只上一天的簡介課...呵)。這種爽的感覺,言語難以形容啊。(總算可以好好睡個覺了~~~)
後記:作品的審查初步結束,雖然沒有進決賽,但還是很有成就感,畢竟全國性的程式設計比賽,我算是頭一遭啊。接下來,以後有機會上Android Market再讓大家免費使用囉。(Wow,從沒想到我也是個Freeware的作者了。哈!)
青椒小黃貓

以下是小弟自己錄的軟體說明:


2009年6月21日 星期日

迎接上輩子情人

6/20晚上睡覺前,老婆說有點陣痛,但不是很規律。於是我上網查了一下,如 果陣痛在五分鐘以內而且規律的話再到醫院即可。否則不少新手懷孕媽媽都因太早到醫院而被醫院"請"回家休息。因此,我請老婆忍耐點,並計錄陣痛時間。但一 直到睡前陣痛都不甚規律而且大約十五分鐘左右的陣痛頻率,我們也就不以為意紛紛睡去。
6/21零晨一點多,老婆哭著叫醒熟睡中的我,說她痛到破水,可能要生了。我就拿了事先準備的物品,載著她到大林慈濟醫院。這半小時的路程感覺開了很久, 一方面知道老婆的痛,另一方面心裏也緊張。雖然半夜路上沒什麼車,但我仍以平穩不急燥的方式將車子開到醫院急診室門口。車停之後,我開了車門,太太因痛而 無法下車,門口警衛以及我都靜靜等她陣痛暫緩過後才上輪椅推進醫院。
我停車回來,看老婆被安排於待產床區,於是就下樓去辦理住院手續。約莫十分鐘回來,護士小姐一見我就說太太要生了,是急產。於是她馬上聯絡醫生,五分鐘後醫生竟然從小門冒出來。我心想怎麼可能這麼快?結果是因為當天是好日子,他於五點有預約剖腹生產,所以睡醫院宿舍。因此可以馬上趕過來。哇。真幸運啊。所以就放下心中大石,換了手術衣跟醫生進產房陪產。
一進產房開始拿起相機攝影及拍照,結果護士居然說生產過程不可以拍,要寶寶出來才行,我當場傻眼,好在醫生有暗示我偷拍了一些。(醫生後來跟我說,有些事只能做不能說...呵)
過程中太太用力沒幾次,就很快地且很順利將女兒生出來。不像老大還得動用到吸引器,搞得他出生後頭尖尖的幾個星期。
女兒平安出生,大家都很高興,也感謝相關幫忙的人。感覺她跟我很有緣,希望她平安長大,成為人見人愛的有用之人。就這樣,上輩子的情人正式成為家裏的一份子了。

2009年4月24日 星期五

蔥蔥開花結果

第一次種植蔥也算滿順利的。除了蔥白沒有理想中長之外,其他都還滿成功的。由於蔥長的很好,數量不少,於是太太就直接摘下來炒青蔥,味道真是甜美啊;而且,還有用自己種的蔥做青蔥麵包,味道也很讚。
當中最令我意外的是,我的蔥居然開花了!我這個都市土包子,幾乎每餐之中都有蔥這個大配角存在,但是長那麼大,從來都不知道蔥會開花,更別說是看過蔥開花了。這次蔥開花,我兒子也很興奮。不但如此,他現在只要看到蔥都會說"爸爸種的",好像我是蔥的代言人。
原來的蔥整體收成後,還留下一些,但是經過颱風大雨之後,根有點爛掉,於是把蔥整個處理掉,加一些天然肥料並休耕中....
這次的花我有留下一些,乾燥後取下種子保存,待下次要種的時候,再重新撥種囉。總之,這次蔥的種植真的很成功,也是一個很棒的生活體驗。




2009年3月10日 星期二

撞牆了

最近撞球不知道怎麼搞的,姿式一直很不順,覺得怪怪的。一覺得怪怪的,自然準度就跑掉。我的"必也射乎"撞友說這是所謂的撞牆期。離上次撞牆期有一段時間了,只是不知道為什麼最近就是覺的很怪。看來需要有人指導我一下,讓我破牆了。

2009年2月8日 星期日

蔥蔥長大

回想上次親自種東西是小學三年級,那時為了觀察紅豆、綠豆、花生...等豆類的成長,必需實行的自然課實驗。長大以後,因為是都市小孩,所以也沒有機會種種東西,頂多是在自家樓頂上幫媽媽種的花澆澆水。
認識太太之後,由於她是鄉下孩子,使我有機會體驗鄉村生活並且與農作物有更進一步的接觸與了解。岳父務農,種了水稻及不少柳丁。我有機會也幫他做一些農 事,並且也學會如何開鐵牛。岳母平日種種菜,我也有機會幫忙澆水及收割。這些農事是我這台北都市小孩從來沒有機會接觸的,在接觸之後,居然讓我發現對務農 的興趣。

三四個月前,為了小孩的成長,搬新家 到一個較大的公寓。此公寓每間房間幾乎都有個種花的小陽台,所以,我就想利用這些小陽台來種點東西,滿足一下我對務農的渴望。三個月某一天的假日,我將小 陽台的土進行鬆土。天啊,可能是前房客N年沒種東西了,土壤很硬,使用花了不少力氣在人工鬆土上面。接下來,想想要種什麼呢?我想種一些能吃的東西。剛好 想到常常老婆作飯要用蔥,所以就拿蔥當第一炮囉。

岳母知道我想種蔥,就準備一些蔥苗給我,讓我也順利完成種植的工作。由於土壤太貧瘠了,因此,我將一些水果及小孩沒喝完的牛奶發酵後,當成天然肥料。另外,蔥的種植我也沒經驗,所以上網查了一些資料,也了解什麼叫培土,並且如何處理天然肥料。

每天早上起床上班前,除了把要穿的衣服燙一下之外,倒是多了一個為蔥澆水的動作。但也很高興每天看著蔥長大,如同看自己小孩長大一樣的喜悅。三個月過去了,蔥長的還算可以,雖然離理想還有一段距離,但至少是個好的開始。



[種植的情況-近看]



[種植的情況-完整Top View]



[種植的情況-從小陽台看出去]

剛好前幾天拔牙,想煮個稀飯來吃,於是採收一小株來使用。洗完之後,我生吃一下,蔥白很甜,真的很不錯。只是蔥白沒有很長,可能是培土不夠的關係,下次再來改進吧。總之,第一次種植,第一次收成的感覺真有成就感。



[剛採收下一株]



[採收清洗後分成三株]

2009年2月4日 星期三

拜痛牙所賜而悠閒一天

可能是運氣不好吧,口中四顆智齒都不聽話的亂長,而且歪的利害。約莫六七年前,左下智齒斜長而干涉旁邊的臼齒,使得臼齒被推擠而產生疼痛,在不得已的情況 下請牙醫拔除。當時這顆智齒對醫生來說是個挑戰,因為沒辦法直接拔,只好先切成二塊,分別拔出。有這次經驗後,對拔智齒這件事可說是敬而遠之。
除夕當天,發覺口腔壁破個小洞而疼痛。自我檢查一下,發覺是左上的智齒因為蛀牙造成齒邊鋒利而割破口腔壁。但過年期間又沒醫生可看,讓我痛了一個星期。今 天去看牙醫,醫生說我全部的牙齒只有這顆智齒有蛀牙,裏面已經有些蛀成中空了,最好拔掉。於是就拔掉它,也順便讓我有機會在家休息一整天。
(我拔掉的智齒,有點難看,介意的人請不要看...)
www.flickr.com/photos/dwankun/3253428276/in/photostream/

今天難得悠閒一天,正好買的新書也到貨,所以把阿扁的台灣的十字架看完。看完之後,感覺阿扁這輩子都還沒有時間好好享福。從小貧苦,當律師後又幫美麗島案 辯護,之後就進了政治圈這條不歸路。好不容易總統卸任,卻又因國務機要費被押,真是無耐。不過書中,提到一些與目前當政者或綠營的一些過去事,只能看看而 已。因為都是單方說詞,就像夫妻吵架,各說各話,各說各有理,旁人是看不清的。總之,心地善良的人是不適合從政的,就像阿扁一樣,當初美麗島事件,其實對 他是有很大的律師生涯風險,但他仍勇往直前。反觀主導政治清算的幕後黑手,才真正能在政治圈長久生存。
我沒有政黨色彩,只談是非。但對於這次未審先押或先判而感到走民主人權退路。唉~ 可惜。

2009年1月14日 星期三

無煙裊裊的感覺真棒

小時候偷抽煙應該大家都有過吧。回想小時候,某天某月偷偷拿了爸爸的煙點了一下,學大人吞雲吐霧。誰知那時太用力吸了一口,馬上嗆到咳了一會兒,也因此感受到香煙真的很臭。如此臭的東西怎麼還會有人要抽呢?(這是當時心中的疑問)
之後,專科時代,由於家離學校很遠,必定得坐公車到學校上學。很多次公車司機在冷氣車裏面吸煙,我被香煙的味道搞得快吐了,真的很不舒服。從那時候,我就知道,我這一輩子不可能抽煙了。因為,我跟香煙不合。況且香煙真的不香,而是真的很臭。>_<
我 愛打撞球,只是撞球場總是炊煙裊裊,令人難受;但又礙於想打球,只好忍受。甚至有時還想,為什麼打撞球的人口中可能只有二成的人抽煙,但卻要八成不吸煙的 人來忍受這種惡劣的環境,真的不合理。難道,那些抽煙的人如果不抽煙就不會撞球了嗎?呵。而且我還在想,怎麼沒有一家撞球場敢宣布全面禁煙的。是怕生意不 好嗎?....撞球族抽煙人口比例又沒那麼高...總之,就是沒有一家撞球場的老闆想得罪那二成的吸煙族而少賺那些錢,反到沒有去思考如果環境弄好一點, 那另外八成的撞球族可能又會帶其他人進來享受良好的休閒環境。
就在2009年1月11日煙害防治法實行了。今天,我又去常去的撞球場打球。打了二小時下來,我居然跟往常不一樣覺得累,反而精神還很好。難道是沒有煙燻暈我?而且回到家,衣服完全沒有香煙的味道,太棒了。這樣以後就不用再擔心為了撞球的興趣,而去吸那些不健康的二手煙了。這一天,真的等得我好久好久。....太感動了。(就算時間很晚了,我還是要把感覺寫出來~)


信仰 X 貢丸店 X 搬芒果

這篇文章,想跟大家談談 信仰 。 信仰,一般人會想到的是信教,無論是佛教、基督教或懶......惰的教。 但我個人對信仰的解讀比較不同,我所認知的信仰比較偏向信念。也就是說,不單單是信教般地相信一個神或神的代言人所講的話(佛經、聖經、某某上人語錄...),而是「任何的人事物讓你...