代码大全简单整理

没记错的话,《代码大全》是我本科三年级时用过的教材,现在毕业工作了准备再次品读一番经典,将一些较为实用的代码构建技巧整理一下。

1

(P445)过分深层的缩进,或者“嵌套”,是产生混乱代码的罪魁祸首之一。在编程中,应该避免超过3到4层的嵌套。针对一份糟糕的深层嵌套代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (inputStatus == InputStatus_Success) {
// lots of code
...
if (printerRoutine != NULL) {
// lots of code
...
if (SetupPage()) {
// lots of code
...
if (AllocMem(&printData)) {
// lots of code
...
}
}
}
}

可以用break块来简化嵌套if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
do {
// begin break block
if (inputStatus != InputStatus_Success) {
break; // break out of block
}
// lots of code
...
if (printerRoutine == NULL) {
break; // break out of block
}
// lots of code
...
if (!SetupPage()) {
break; // break out of block
}
// lots of code
...
if (!AllocMem(&printData)) {
break; // break out of block
}
// lots of code
...
} while(FALSE); // end break block

其他减少嵌套层次的技巧:

  • 重复判断一部分条件
  • 转换成if-then-else
  • 转换成case语句
  • 把深层嵌套的代码提取成单独的子程序
  • 使用对象和多态派发

2

(P614)有时候,在复杂的逻辑链路中,通过使用查询表会更加高效。假设所有对象属于ABC三个组,需要对这些对象指定一个类标号。复杂的逻辑结构可能如下:

1
2
3
4
5
6
7
8
9
10
11
12
if ((a && !c) || (a && b && c)) {
category = 1;
}
else if ((b && !a) || (a && c && !b)) {
category = 2;
}
else if (c && !a && !b) {
category = 3;
}
else {
category = 0;
}

如果使用查询表,修改起来更容易,代码性能也更高:

1
2
3
4
5
6
7
static int categoryTable[2][2][2] = {
// !b!c !bc b!c bc
0, 3, 2, 2, // !a
1, 2, 1, 1 // a
}
...
category = categoryTable[a][b][c];

3

(P621)当循环的判断条件是一个复合判断的时候,可以通过简化判断来节省运行时间。如果循环是一个查找循环,简化方法之一就是使用一个哨兵值(sentinel value)。
一个搜索循环的例子如下,每一次搜索需要检查是否发现了所要找的值,另一方面要检查它是否遍历了所有的值,在循环内部又要检查是否当前是否是需要查找的元素,因此每次迭代实际执行了三次判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
found = FALSE;
i = 0;
while ((!found) && (i < count)) {
if (item[i] == testValue) {
found = TRUE;
} else {
i++;
}
}
if (found) {
...
}

可以通过在查找范围的末尾设置哨兵值来中值循环,使每一次迭代只需要执行一次判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
// set sentinel value, preserving the original value
initialValue = item[count];
item[count] = testValue;
i = 0;
while (item[i] != testValue) {
i++;
}
// check if value was found
if (i < count) {
...
}

4

使用加法代替乘法

5

使用整型数而非浮点数

6

数组维度尽可能少