老程序员教我的编程技巧
在编程中,我们经常会遇到问题(俗称bug),找出一个bug很费时间,那么那么我们该如何让程序少出bug,增加编程速度呢?这里有一些老程序员教我的编程技巧,可以用来借鉴和参考一下。1. 先完成简单的功能, 再逐步增加复杂度
举例来说, 直接求多个数的 min/max, 比较复杂, 我们可以先从最简单的开始。
先求两个数的 min/max。
1 int max(int a, int b) { 2 if (a > b) return a; 3 else return b; 4 }
或是:
1 int min(int a, int b) { 2 if (a < b) return a; 3 else return b; 4 }
2. 求多个数的 min/max。
1) hardcode(硬编码):
1 int hard_max_3(int a, int b, int c) { 2 if (a > b && a > c) return a; 3 if (b > a && b > c) return b; 4 if (c > a && c > b) return c; 5 if (? ? ? ? ) return ? ? ? ? ;
6 }
2) 用两个数的 min/max 来求三个数的 min/max。
1 int max(int a, int b) { 2 if (a > b) return a; 3 else return b; 4 } 5 6 int max_3(int a, int b, int c){ 7 return max(a, max(b, c)); 8 }
注意对比1号和2号的max_3,1号代码,也就是硬编码,整整使用了五行来算出这个结果,而2号只用了两行,就算出了结果。而且硬编码,你得保证他全部的情况都覆盖了,所以你要想很久,就很累。不光麻烦,还容易出错。
3) 用三个数的 min/max 来求四个数的 min/max。
1 int max_3(int a, int b, int c){ 2 return max(a, max(b, c)); 3 } 4 5 int max_4(int a, int b, int c, int d) { 6 return max(a, max_3(b, c, d)); 7 }
此时如果你还想用硬编码编写4个数的最大值或者是最小值,我劝你还是算了吧。毕竟写三个就已经很累了,何况是4个呢。
3. 先写主框架, 再补充细节。
题目如下:
输入三位同学的期末考试成绩,分别判断以下条件,满足条件,执行动作:

请看以下代码:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 5 int max(int a, int b) { 6 if (a > b) return a; 7 else return b; 8 } 9 10 int min(int a, int b) { 11 if (a < b) return a; 12 else return b; 13 } 14 15 } 16 int max_3(int a, int b, int c){ 17 return max(a, max(b, c)); 18 } 19 20 21 int max_4(int a, int b, int c, int d) { 22 //return max(a, max(b, max(c, d))); 23 return max(max(a, b), max(c, d)); 24 return max(a, max_3(b, c, d)); 25 } 26 27 int min_3(int a, int b, int c) { 28 return min(a, min(b, c)); 29 } 30 31 double average(double a, double b, double c) { 32 return (a + b + c) / 3; 33 } 34 35 int median(int a, int b, int c) { 36 return 0; 37 } 38 39 bool diff(int a, int b, int c) { 40 return 0; 41 } 42 bool diff_x(int a, int b, int c) { 43 return false; 44 } 45 46 int main() { 47 int a, b, c; 48 scanf("%d%d%d", &a, &b, &c); 49 if (a > 90 && b > 90 && c > 90) { 50 printf("%d", max_3(a, b, c)); 51 } 52 else if (a < 60 && b < 60 && c < 60) { 53 printf("%d", min_3(a, b, c)); 54 } 55 else if (a >= 60 && a <= 90 && 56 b >= 60 && b <= 90 && 57 c >= 60 && c <= 90 && diff(a, b, c)) 58 { 59 printf("%.2lf", average(a, b, c)); 60 } 61 else if (a >= 60 && a <= 90 && 62 b >= 60 && b <= 90 && 63 c >= 60 && c <= 90 && diff_x(a, b, c)) 64 { 65 printf("%d", median(a, b, c)); 66 } 67 else { 68 printf("数据差异过大"); 69 }
重点关注第35到第45行。这3个函数median、diff和diff_x,我都没有写任何内容。但是第49行开始,一直到69行。判断语句完成得非常的完善。这就叫做先写主框架,再完成细节。如果你先写细节,在写主框架的话,即使细节很完美,都很有可能导致细节套不进主框架里面。
4. 每个功能写成一个函数。
还是以第3点的例子为例:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 5 int max(int a, int b) { 6 if (a > b) return a; 7 else return b; 8 } 9 10 int min(int a, int b) { 11 if (a < b) return a; 12 else return b; 13 } 14 15 } 16 int max_3(int a, int b, int c){ 17 return max(a, max(b, c)); 18 } 19 20 21 int max_4(int a, int b, int c, int d) { 22 //return max(a, max(b, max(c, d))); 23 return max(max(a, b), max(c, d)); 24 return max(a, max_3(b, c, d)); 25 } 26 27 int min_3(int a, int b, int c) { 28 return min(a, min(b, c)); 29 } 30 31 double average(double a, double b, double c) { 32 return (a + b + c) / 3; 33 } 34 35 int median(int a, int b, int c) { 36 return 0; 37 } 38 39 bool diff(int a, int b, int c) { 40 return 0; 41 } 42 bool diff_x(int a, int b, int c) { 43 return false; 44 } 45 46 int main() { 47 int a, b, c; 48 scanf("%d%d%d", &a, &b, &c); 49 if (a > 90 && b > 90 && c > 90) { 50 printf("%d", max_3(a, b, c)); 51 } 52 else if (a < 60 && b < 60 && c < 60) { 53 printf("%d", min_3(a, b, c)); 54 } 55 else if (a >= 60 && a <= 90 && 56 b >= 60 && b <= 90 && 57 c >= 60 && c <= 90 && diff(a, b, c)) 58 { 59 printf("%.2lf", average(a, b, c)); 60 } 61 else if (a >= 60 && a <= 90 && 62 b >= 60 && b <= 90 && 63 c >= 60 && c <= 90 && diff_x(a, b, c)) 64 { 65 printf("%d", median(a, b, c)); 66 } 67 else { 68 printf("数据差异过大"); 69 }
从第5到第42行,仅仅是为了求出一组数字的最大数和最小数,我们就写了很多的函数。
5. 对复杂的工程, 变量名和函数名要与实际用途相符。
题目描述
学校给同学们发文具,每个同学都会拿到一定数量的铅笔和橡皮。一共有n个同学,请你计算同学们一共拿到了多少铅笔和橡皮。
输入n,代表有n个同学。接下来n行,每行两个正整数,分别为某个同学收到的铅笔和橡皮数量。
输出同学们一共拿到了多少铅笔,多少橡皮,两个数字之间以空格分开。
代码如下:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int main(){ 5 int num_of_stu = 0; 6 scanf("%d",&num_of); 7 int i = 0; 8 int pencil = 0; 9 int eraser = 0; 10 int total_p = 0; 11 int total_e = 0; 12 while(i < num_of){ 13 scanf("%d%d",&pencil,&eraser); 14 total_p += pencil; 15 total_e += eraser; 16 i += 1; 17 } 18 printf("%d %d",total_p,total_e); 19 return 0; 20 21 }
在这段代码中我们定义了6个变量。每个变量的含义都不相同,所以变量名一定要与变量的用处相符。将命名的好处是,在你维护的时候就可以知道这个变量是做什么用的,
6. scanf () 中的格式类型, 要与实际类型相符, 否则容易溢出。
请看下面代码:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int main() { 5 char a = '0'; 6 scanf("%d", &a); 7 printf("%c", a); 8 return 0; 9 }
我要输入一个字符,再输出这个字符。如果你运行上面这段代码,会发现你不会得到你想要的输出。那么这是为什么呢?我们用下面的程序来看一下。
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int main() { 5 char b = ' '; 6 float c = 0.0; 7 double d = 0.0; 8 long x = 0; 9 short y = 0; 10 int a = ' '; 11 printf("int: %d\n", sizeof(a)); 12 printf("char: %d\n", sizeof(b)); 13 printf("float: %d\n", sizeof(c)); 14 printf("double: %d\n", sizeof(d)); 15 printf("long: %d\n", sizeof(x)); 16 printf("short: %d", sizeof(y)); 17 return 0; 18 }
输出如下:

所以整型要占用4个字节,而字符型只要占用一个字节。所以如果你把整型变量装在字符型的“抽屉”里,那它就会溢出了。
7. 在实现特定功能时, 为快速检查功能是否正确, 可以先不要 scanf, 给变量直接赋值,
等功能基本完成或确认无误后, 再注释掉赋值语句, 恢复 scanf。
题目描述
一棵苹果树上结了 n 个果,不幸的是被一条虫子盯上了。虫子每 x 小时能吃掉一个苹果,好在这个虫子比较傻,它吃完一个苹果之前不会吃另一个,
那么经过 y 小时,树上还剩下多少个完整的苹果?
代码如下:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int main(){ 5 int a,b,c; 6 a = b = c = 0; 7 scanf("%d%d%d",&a,&b,c); 8 if (c % b != 0){ 9 printf("%d",a-(c / b + 1)); 10 } 11 else{ 12 printf("%d",a-(c / b)); 13 } 14 return 0; 15 }

运行之后会发现程序有错误,什么都不输出,请问你知道为什么吗?
我们先把scanf注释掉,然后呢,给a、b、c分别赋一个值来试一下。
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int main(){ 5 int a,b,c; 6 a = 10; 7 b = 4; 8 c = 9; 9 //scanf("%d%d%d",&a,&b,c); 10 if (c % b != 0){ 11 printf("%d",a-(c / b + 1)); 12 } 13 else{ 14 printf("%d",a-(c / b)); 15 } 16 return 0; 17 }
此时,输出结果就变成正确的了:

仔细观察原来的代码,你会发现scanf少了一个取址符。
呵呵🙂,真是个“低级错误”!
以上就是老程序员教给我的7个小妙招。
浙公网安备 33010602011771号