双人项目之代码规范
该课程的双人项目是蒋协成与韩皓天同学合作的,在阅读了老师发的《java开发手册》v1.5.0华山版和华为编码规范(c语言版)之后,我意识到代码规范的重要性,在老师发资料的基础上,我再在网上查阅资料以及结合自己平时在编程时,一些会对自己在debug或者调试时有帮助的一些小方法,我们总结出了以下几点代码规范。
1) 空行
空行能隔开程序段落,将使程序的布局更加清晰。
用空行的情况:
1、定义变量后要空行。尽可能在定义变量的同时初始化该变量,即遵循就近原则。如果变量的引用和定义相隔比较远,那么变量的初始化就很容易被忘记。若引用了未被初始化的变量,就会导致程序 出错。
2、每个函数定义结束之后都要加空行。
总结:两个相对独立的程序块、变量说明之后必须要加空行。比如上面几行代码完成的是一个功能,下面几行代码完成的是另一个功能,那么它们中间就要加空行。这样看起来更清晰。
2) 空格
1、关键字之后要留空格。像 const、case 等关键字之后至少要留一个空格,否则无法辨析关键字。像 if、for、while 等关键字之后应留一个空格再跟左括号(
,以突出关键字。
2、函数名之后不要留空格,应紧跟左括号(
,以与关键字区别。
3、、,
、;
这三个向前紧跟;紧跟处不留空格。
4、“,”
之后要留空格。如果;
不是一行的结束符号,其后要留空格。
5、赋值运算符、关系运算符、算术运算符、逻辑运算符、位运算符
3) 成对书写
成对的符号一定要成对书写,如 ()、{}。不要写完左括号然后写内容最后再补右括号,这样很容易漏掉右括号,尤其是写嵌套程序的时候。
4) 缩进
缩进是通过键盘上的 Tab 键实现的,缩进可以使程序更有层次感。原则是:如果地位相等,则不需要缩进;如果属于某一个代码的内部代码就需要缩进。
5) 对齐
对齐主要是针对大括号{}
说的:
1、{
和}
分别都要独占一行。互为一对的{
和}
要位于同一列,并且与引用它们的语句左对齐。2、{}
之内的代码要向内缩进一个 Tab,且同一地位的要左对齐,地位不同的继续缩进。
6) 代码行
1、一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且便于写注释。
2、if、else、for、while、do 等语句自占一行,执行语句不得紧跟其后。此外,非常重要的一点是,不论执行语句有多少行,就算只有一行也要加{}
,并且遵循对齐的原则,这样可以防止书写失误。
7) 注释
C语言中一行注释一般采用//…
,多行注释必须采用/*…*/
。注释通常用于重要的代码行或段落提示。在一般情况下,源程序有效注释量必须在 20% 以上。虽然注释有助于理解代码,但注意不可过多地使用注释。
下面我举一个我之前写过的线段树的模板,用来详细印证我上面几点:
1 //线段树模板,node一般写1,递归中的node不需要修改 2 //线段树的题一般 3 #include <bits/stdc++.h> 4 #define MAX 2333 5 typedef long long LL; 6 using namespace std; 7 8 9 //声明 10 //开四倍空间 11 int tree[4*MAX]; 12 int lz[4*MAX]; 13 14 //初始化树的数组 15 void init(){ 16 memset(tree,0,sizeof(tree)); 17 } 18 19 20 //建树,将数组tree变成一个树,用数组的方式来存数据 21 void build(int node,int l,int r){ 22 if(l == r){ // 到达叶子节点,赋值 23 cin >> tree[node]; 24 return; 25 } 26 int mid = (l+r)/2; 27 build(node*2,l,mid); // 进入子树开始递归左 28 build(node*2+1,mid+1,r);//右子树 29 tree[node] = tree[node*2] + tree[node*2 + 1]; // 回溯,这两个的父节点 30 } 31 32 33 //单点修改 34 //单点更新,n为更新值,index为更新点,lr为更新范围 35 void update(int n,int index,int l,int r,int node){ 36 if(l == r) { 37 tree[node] += n; // 更新方式,可以自由改动 38 return; 39 } 40 int mid = (l+r) / 2; 41 // push_down(node,mid-l+1,r-mid); 若既有点更新又有区间更新,需要这句话 42 if(index <= mid){ 43 update(n,index,l,mid,node*2); 44 }else{ 45 update(n,index,mid+1,r,node*2+1); 46 } 47 tree[node] = tree[node*2] + tree[node*2 + 1]; // 回溯过程,需要将线段树上层数据更新 48 } 49 /* 50 l与r就是指当前节点的区间范围,刚开始肯定是填1,8了,因为线段树的最上边节点代表的范围(参照上图的白色区间字体)就是1,8。 51 那么,如果l==r,就说明到达了叶子节点,当然就是需要更新的节点了。 52 如何进入递归?就跟二分一样,index与mid进行判断,看是走左子树还是右子树。最后一定不要忘记回溯,因为叶子节点更新后,上层节点的值也需要更新,这样才算维护了线段树。 53 54 里面有一行注释的代码,这里需要把后面的懒惰标记、区间操作学完才能理解。现在就当不存在吧。 55 */ 56 57 58 //懒惰标记 59 //这里不需要递归是因为,它是放在其他递归函数里一起调用的 60 void push_down(int node,int l,int r){ 61 if(lz[node]){ 62 int mid = (l+r) / 2; 63 lz[node*2] += lz[node]; 64 lz[node*2 + 1] += lz[node]; 65 // 注意线段树的数据更新方式要一致 66 tree[node*2] += 1LL*(mid - l + 1)*lz[node]; 67 tree[node*2 + 1] += 1LL*(r - mid)*lz[node]; 68 lz[node] = 0; 69 } 70 } 71 72 // 区间更新,lr为更新范围,LR为线段树范围,add为更新值 73 void update_range(int node,int l,int r,int L,int R,int add){ 74 if(l <= L && r >= R){ 75 lz[node] += 1LL*add; 76 tree[node] += 1LL*(R - L + 1)*add; // 更新方式 77 return; 78 } 79 push_down(node,L,R); 80 int mid = (L+R) / 2; 81 if(mid >= l) update_range(node*2,l,r,L,mid,add); 82 if(mid < r) update_range(node*2 + 1,l,r,mid+1,R,add); 83 tree[node] = tree[node*2] + tree[node*2 + 1]; 84 } 85 86 // 区间查找 87 LL query_range(int node,int L,int R,int l,int r){ 88 if(l <= L && r >= R) return tree[node]; 89 push_down(node,L,R); 90 int mid = (L+R) / 2; 91 LL sum = 0; 92 if(mid >= l) sum += query_range(node*2,L,mid,l,r); 93 if(mid < r) sum += query_range(node*2 + 1,mid+1,R,l,r); 94 return sum; 95 } 96 97 98 //如果用了lazy会更麻烦,用以下操作 99 /* 100 bool cleck(int node,int l,int r){ 101 // 剪枝条件 102 } 103 104 void update_range(int node, int l, int r, int L, int R) { 105 if (L == R) { 106 tree[node] = 1; // 更新方式 107 return; 108 } 109 int mid = (L + R) / 2; 110 if (mid >= l && cleck(node*2,L,mid)) update_range(node * 2, l, r, L, mid); 111 if (mid < r && cleck(node*2+1,mid+1,R)) update_range(node * 2 + 1, l, r, mid + 1, R); 112 tree[node] = tree[node * 2] + tree[node * 2 + 1]; 113 } 114 */ 115 116 int main(){ 117 init(); 118 build(1,1,8); 119 //system("pause"); 120 return 0; 121 }
可以看到,我之前写得代码,注释很详细,关键地方也有小的注释,空格换行等细节都符合上述代码规范,把线段树这个复杂的问题在看到我的模板时,能一下子就找到线段树的思想,然后修改,方便而快捷。