需要林锐《高质量编程指南》原文的请在回复中留下电子邮箱.请在迅雷中自行搜索.
11月14日
1.头文件规范:
如:
*-----------------------------------------------------------
/**/ /*
RB-Tree的插入和删除操作的实现算法
1.版权声明:
Copyright @ 2006,pengkuny( http://www.cppblog.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
哈哈 阅读(3159)
评论(38) 编辑 收藏 引用