需要林銳《高質量編程指南》原文的請在回復中留下電子郵箱.請在迅雷中自行搜索.
11月14日
1.頭文件規范:
如:
*-----------------------------------------------------------
/**/ /*
RB-Tree的插入和刪除操作的實現算法
1.版權聲明:
Copyright @ 2006,pengkuny( http://www.shnenglu.com/pengkuny ),All rights reserved.
您可以自由的傳播,修改這份代碼,轉載處請注明原作者

2.文件名稱:

3.參考資料:
1) <<Introduction to algorithm>>
2) http://www.ececs.uc.edu/ ~franco/C321/html/RedBlack/redblack.html

4.內容摘要:
紅黑樹的幾個性質:
1) 每個結點只有紅和黑兩種顏色
2) 根結點是黑色的
3) 每個葉子結點(空結點被認為是葉子結點)是黑色的
4) 如果一個結點是紅色的,那么它的左右兩個子結點的顏色是黑色的
5) 對于每個結點而言,從這個結點到葉子結點的任何路徑上的黑色結點
的數目相同

5.完成日期:
2006.11.14
------------------------------------------------------------- */
2.【規則】一行代碼只做一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,并且方便于寫注釋。如:
int width; // 寬度
int height; // 高度
int depth; // 深度
x = a + b;
y = c + d;
z = e + f;
if (width < height)
{
dosomething();
}
for (initialization; condition; update)
{
dosomething();
}
// 空行
other();
3.【建議】盡可能在定義變量的同時初始化該變量(就近原則)
如:
int width = 10 ; // 定義并初紿化width
int height = 10 ; // 定義并初紿化height
int depth = 10 ; // 定義并初紿化depth
4.空格寫法:
【規則】if、for、while等關鍵字之后應留一個空格再跟左括號‘(’,以突出關鍵字。
【規則】函數名之后不要留空格,緊跟左括號‘(’,以與關鍵字區別。
【規則】‘(’向后緊跟,‘)’、‘,’、‘;’向前緊跟,緊跟處不留空格。
【規則】‘,’之后要留空格,如Function(x, y, z)。如果‘;’不是一行的結束符號,其后要留空格,如for (initialization; condition; update)。
【規則】賦值操作符、比較操作符、算術操作符、邏輯操作符、位域操作符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后應當加空格。
【規則】一元操作符如“!”、“~”、“++”、“--”、“&”(地址運算符)等前后不加空格。
5.【建議】對于表達式比較長的for語句和if語句,為了緊湊起見可以適當地去掉一些空格,如for (i=0; i<10; i++)和if ((a<=b) && (c<=d))
6.長行拆分:
【規則】長表達式要在低優先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當的縮進,使排版整齊,語句可讀。
7.應當將修飾符 * 和 & 緊靠變量名
例如:
char *name;
int *x, y; // 此處y不會被誤解為指針
8.注釋的寫法:
程序塊的注釋常采用“/*…*/”,行注釋一般采用“//…”。
【規則】注釋是對代碼的“提示”,而不是文檔。程序中的注釋不可喧賓奪主,注釋太多了會讓人眼花繚亂。注釋的花樣要少。
【規則】邊寫代碼邊注釋
【規則】注釋的位置應與被描述的代碼相鄰,可以放在代碼的上方或右方,不可放在下方。
9.類的版式:
我們不可以濫用類的封裝功能,不要把它當成火鍋,什么東西都往里扔。
將public類型的函數寫在前面,而將private類型的數據寫在后面,“以行為為中心”,重點關注的是類應該提供什么樣的接口(或服務)。
10.命名規則:
切忌使用漢語拼音來命名。
【規則】命名規則盡量與所采用的操作系統或開發工具的風格保持一致。
例如Windows應用程序的標識符通常采用“大小寫”混排的方式,如AddChild。而Unix應用程序的標識符通常采用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起用。
【規則】變量的名字應當使用“名詞”或者“形容詞+名詞”。
例如:
float value;
float oldValue;
float newValue;
【規則】全局函數的名字應當使用“動詞”或者“動詞+名詞”(動賓詞組)。類的成員函數應當只使用“動詞”,被省略掉的名詞就是對象本身。
例如:
DrawBox(); // 全局函數
box->Draw(); // 類的成員函數
【建議】盡量避免名字中出現數字編號,如Value1,Value2等,除非邏輯上的確需要編號。這是為了防止程序員偷懶,不肯為命名動腦筋而導致產生無意義的名字(因為用數字編號最省事)。
11月24日
1.簡單的Windows應用程序命名規則:
【規則】類名和函數名用大寫字母開頭的單詞組合而成。
例如:
class Node; // 類名
void SetValue(int value); // 函數名
【規則】變量和參數用小寫字母開頭的單詞組合而成。
例如:
BOOL flag;
int drawMode;
【規則】常量全用大寫的字母,用下劃線分割單詞。
例如:
const int MAX = 100;
const int MAX_LENGTH = 100;
【規則】靜態變量加前綴s_(表示static)。
例如:
static int s_initValue; // 靜態變量
【規則】全局變量加前綴g_(表示global)。
【規則】類的數據成員加前綴m_(表示member),這樣可以避免數據成員與成員函數的參數同名。
2.允許復合表達式存在的理由是:(1)書寫簡潔;(2)可以提高編譯效率。但要防止濫用復合表達式。
3.布爾變量與零值比較:
【規則1】不可將布爾變量直接與TRUE、FALSE或者1、0進行比較。
根據布爾類型的語義,零值為“假”(記為FALSE),任何非零值都是“真”(記為TRUE)。TRUE的值究竟是什么并沒有統一的標準。例如Visual C++ 將TRUE定義為1,而Visual Basic則將TRUE定義為-1。
假設布爾變量名字為flag,它與零值比較的標準if語句如下:
if (flag) // 表示flag為真
if (!flag) // 表示flag為假
其它的用法都屬于不良風格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
對于林銳提出的規則我有質疑,既然bool型的值按定義記為FALSE和TRUE,
那么我根本不關心FALSE和TRUE的具體值,那么
if (flag == TRUE)
又有何不可?系統總不會把TRUE定義為0吧?(如果是這樣,林銳還是對的)
4.整型變量與零值比較:
【規則】應當將整型變量用“==”或“!=”直接與0比較。
與零值比較的標準if語句如下:
if (value == 0)
if (value != 0)
不可模仿布爾變量的風格而寫成
if (value) // 會讓人誤解 value是布爾變量
if (!value)
5.浮點變量與零值比較:
if ((x>=-EPSINON) && (x<=EPSINON))
6.指針變量與零值比較:
if (p == NULL) // p與NULL顯式比較,強調p是指針變量
if (p != NULL)
7.為防止出錯:
為了防止將 if (p == NULL) 誤寫成 if (p = NULL),而有意把p和NULL顛倒。
編譯器認為 if (p = NULL) 是合法的,但是會指出 if (NULL = p)是錯誤的,
因為NULL不能被賦值。
if (condition) //不良風格,容易出錯
return x;
return y;
改寫為
if (condition)
{
return x;
}
else
{
return y;
}
或者改寫成更加簡練的
return (condition ? x : y);
8.循環語句的效率:
【建議】在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少CPU跨切循環層的次數。
【建議】如果循環體內存在邏輯判斷,并且循環次數很大,宜將邏輯判斷移到循環體的外面。
如果老要進行邏輯判斷,打斷了循環“流水線”作業,使得編譯器不能對循環進行優化處理,降低了效率。
但缺點是:程序不簡潔.
9.【建議】建議for語句的循環控制變量的取值采用“半開半閉區間”寫法。
x值屬于半開半閉區間“0 =< x < N”,起點到終點的間隔為N,循環次數為N。非常直觀簡潔.
10.【規則】不要忘記最后那個default分支。即使程序真的不需要default處理,也應該保留語句
default : break;
這樣做并非多此一舉,而是為了防止別人誤以為你忘了default處理。
11.goto的討論:
很多人建議廢除C++/C的goto語句,以絕后患。但實事求是地說,錯誤是程序員自己造成的,不是goto的過錯。goto 語句至少有一處可顯神通,它能從多重循環體中咻地一下子跳到外面,用不著寫很多次的break語句;
就象樓房著火了,來不及從樓梯一級一級往下走,可從窗口跳出火坑。所以我們主張少用、慎用goto語句,而不是禁用。
12.常量的討論:
C語言用 #define來定義常量(稱為宏常量)。
C++ 語言除了 #define外還可以用const來定義常量(稱為const常量)。
在C++中,const定義常量的優勢:
1)類型檢查
2)可以調試
故可以規定:
【規則】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。
【規則】需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部(cpp文件)。
為便于管理,可以把不同模塊的常量集中存放在一個公共的頭文件中。
類中使用const常量:
1)不能在類聲明中初始化const數據成員。
因為類的對象未被創建時,編譯器不知道該成員的值是什么。
const數據成員的初始化只能在類構造函數的初始化表中進行.
2)const數據成員只在某個對象生存期內是常量,而對于整個類而言卻是可變的,
因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。
3)怎樣才能建立在整個類中都恒定的常量呢?
別指望const數據成員了,應該用類中的枚舉常量來實現。
但是缺點很明顯,只能表示有限大小的整型值.
13.函數設計:
C語言中,函數的參數和返回值的傳遞方式有兩種:
值傳遞(pass by value)和指針傳遞(pass by pointer)。
C++ 語言中多了引用傳遞(pass by reference)。
14.風格:
【規則】:
void SetValue(int width, int height); // 良好的風格
void SetValue(int, int); // 不良的風格
float GetValue(void); // 良好的風格
float GetValue(); // 不良的風格
【規則】參數命名要恰當,順序要合理。
一般地,應將目的參數放在前面,源參數放在后面。
如果將函數聲明為:
void StringCopy(char *strDestination, char *strSource);
【規則】如果參數是指針,且僅作輸入用,則應在類型前加const,以防止該指針在函數體內被意外修改。
例如:
void StringCopy(char *strDestination,const char *strSource);
【規則】如果輸入參數以值傳遞的方式傳遞對象,則宜改用“const &”方式來傳遞,這樣可以省去臨時對象的構造和析構過程,從而提高效率。
@#$%:const & 怎么用?
【規則】不要將正常值和錯誤標志混在一起返回。正常值用輸出參數獲得,而錯誤標志用return語句返回。
典型的getchar函數:
可由 int getchar(void); //字符型值和終止值EOF一同返回,不良風格,但用起來方便
改為 BOOL GetChar(char *c);
【建議】有時候函數原本不需要返回值,但為了增加靈活性如支持鏈式表達,可以附加返回值。
char *strcpy(char *strDest,const char *strSrc);
posted on 2006-11-24 16:43
哈哈 閱讀(3166)
評論(38) 編輯 收藏 引用