在有关代码风格的问题中,最为显眼的可以说就是代码的缩进了。所谓缩进,是为了在每一行的代码左端空出一部分长度,使得更加清晰地从外观上看出程序的逻辑结构。先举一个正确缩进的例子:
int kmp_match(char t[], char p[], int flink[], int n, int m)
{
int i = 0, j = 0;
while(i < n)
{
while(j != -1 && p[j] != t[i])
j = flink[j];
if(j == m – 1)
return (i – m + 1);
i++;
j++;
}
return (-1);
}
我在这里,把有嵌套关系的代码行都采用缩进的方式体现出来了。可以看出,如果在书写代码的同时,能够认真地注意缩进,那么有关嵌套方面的错误、包括大括号配对的错误都不可能出现。假设代码被写成了这个样子:
int kmp_match(char t[], char p[], int flink[], int n, int m)
{int i = 0, j = 0;
while(i < n)
{while(j != -1 && p[j] != t[i])
j = flink[j];
if(j == m – 1)
return (i – m + 1);
i++;
j++;
}
return (-1);
}
你还能一眼看得出来每个 while 循环的具体内容是什么吗?因此,正确地进行缩进会大大提高代码的可读性,下面来说说一些基本的缩进规则。
需要缩进的结构
在遇到有关类、结构、函数或过程、以及枚举等等复杂程序结构的定义的时候,我们通常需要将它的内容缩进一层。在 C/C++/C#/Java 语言中,大括号是一个非常明显的标志,凡是遇到大括号,都应该直接联想到缩进。在 Basic 语言中,Class/End Class、Sub/End Sub、Function/End Function、Structure/End Structure、Enum/End Enum 等等这类带有“End”结束的结构中的内容都应该缩进。例如:
public class MyClass : MyBase |
Public Class MyClass Inherits MyBase |
分支结构(包括 if…else 结构、switch/select…case 结构等)和循环结构(包括 for 结构、while/do…while 结构等)都是存在嵌套关系的,因此从条理清晰的角度来说,它同样应该进行缩进书写。
if(a > b) |
If a > b Then |
switch(n) |
Select Case n |
for(i = 1; i <= 100; i++) |
For i = 1 To 100 |
i = 0; |
i = 0 |
缩进的格式
在编译器中,缩进通常用 TAB 键来控制,它通常对应 2 个或者 4 个空格。同一层次的缩进必须严格对齐。
在大括号语法中,缩进时大括号的写法有不同的几种,个人认为,前面所用的那种左右括号单独一行的写法最为清晰,因为可以最好地反映出括号的配对情况。其它的一些写法有:
// 将左大括号放在结构行某尾 |
// 将左大括号与结构内第一条语句写在一起 |
特殊的分支循环结构(单行内容)
很多语言中,分支结构(如 if)和循环结构(如 for)的结构体部分只有一条语句时,写法与包含多条语句时稍有不同。在 C/C++/Java/C# 语言中,大括号可以省略,这时,我们还是应该按照它的逻辑关系进行缩进处理:
if(a > b) |
for(i = 1; i <= 100; i++) |
i = 0; |
在 Basic 中,如果 If 或者 Else 后只有一条语句,就可以与 If/Else 写在同一行中,而不需要 End If 结构。然而那是旧式的写法,从现代意义上来说,建议还是分行书写,并使用 End If 结尾。
长语句换行
有的时候,一条语句会很长,而超出了屏幕的边界。在这种情况下,虽然你可以不换行,但是从外观上来说会显得很不方便。通常,我们都会根据屏幕通常的宽度来对长语句进行换行。换行以后的部分,要相对于原语句缩进一格:
// 这是一条很长的语句:
myvar = myvar1 + myvar2 + myvar3 - myvar4 - myvar5 * myvar6 * myvar7 /
myvar8 / myvar9 + myvar10 + myvar11 - myvar12 – myvar13 * myvar14 *
myvar15 / myvar16;
// 后面的语句恢复正常的缩进位置
在换行时,我们通常在一个变量或者常量之前换行,把逗号之类的分隔符、运算符留在前一行的行尾。
函数调用时,如果参数个数很多,或者要传递的表达式写起来很长,那么也会涉及到长语句换行问题,最基本的原则是:尽可能地在参数与参数之间换行,并将逗号保留在上一行行末:
// 在参数与参数之间换行
printf("This function call has many parameters. %d %d %d %d/n", myvar1,
myvar2, myvar3, myvar4);
在一些必要的情况下,我们为了清晰地列出函数的每一个参数,可以采取类似结构声明的写法:
// 每个参数分行
printf(
"This function call has many parameters. %d %d %d %d/n",
myvar1,
myvar2,
myvar3,
myvar4
);
当传入的表达式较为复杂时,这种写法会显得格外地清晰。类似地,在同时声明多个同一类型的变量时,也可以如此书写:
double myvar1,
myval2,
myvar3,
myvar4;
它的主要目的是便于对单个变量进行注释:
char username[MAXN], // 用户名
password[MAXN], // 密码
desc[MAXN]; // 描述
这里提到的都是一些总结出来的比较常见的情况,它们并不是金科玉律,只是一个建议,但却是一个强烈的建议。在遇到本文没有提到的情况时,可以根据实际情况和需要调整缩进。归根结底是为了更加清晰和正确地反映出代码的逻辑结构。