超干货!计算机机试调bug经验总结!

写在前面

在计算机机试中,调bug的能力尤为重要,怎样在紧张的考试时间内,对代码中出现的问题及时分析和有效解决显得相当关键,而这往往需要充足的经验储备。下面带大家积累一下常见的bug解决经验。

01、所有测试点都是段错误

段错误:一般由数组越界、堆栈溢出等引起。

常见原因如下:

1.1 for循环的内层循环变量误写成外层循环变量导致数组访问发生越界;

1.2 数组开小了导致指针指向未开辟的数组区域发生越界访问;

1.3 大数组写在main函数里耗光栈内存——大数组在main函数里时是存储在栈中,而栈空间在进程创建时初始化,有固定大小。尽量将大数据开全局——全局变量占用的是堆空间,它是按需分配自由增长;

1.4 递归出口写的有问题——递归层数太多导致堆栈溢出

02、有几个测试点是段错误

2.1 未考虑0或边界值情况,例如对一个空数组访问下标;

2.2 对于树来说,未判断当前结点是否为NULL就访问它的值或左右结点;

2.3 while循环的边界条件未判断正确导致访问了数组的非法内存。

03、所有测试点都运行超时

这种情况一般是出现了死循环:

3.1 i--误写成i++;

3.2 while循环边界的判断有问题;

3.3代码使用过于暴力破解的算法,缺乏优化。

04、有几个测试点是段错误

4.1 cin的输入比scanf更耗时,如果个别测试点超时可以考虑是否可以通过优化输⼊将 cin 改成 scanf;

4.2 对数据进行排序的过程中,有很多数据是无效数据,如果对所有数据都排序可能会引起超时,所以可以考虑在放⼊数组之前就做⼀些条件判断剔除无用数据,然后再对数组进行排序;

4.3 如果写了 main 函数之外的其他函数,传引用会⽐传值的⽅式更省时,因为传值是拷贝传参,传引用是传⼊的地址直接在原变量上修改,所以可以考虑优化为 void func(int& a) 的方式传递参数减少耗时;

4.4 在 for 或者 while 循环中的及时判断条件,用 break 提前退出当前层的循环或者直接 return0; 结束程序,可以降低代码运⾏时间;

4.5 for 循环语句里定义 int i 和在外面定义 int i 其实有少许区别:在 for 循环语句里直接定义的 i ,比如 for(int i = 0; i < 10; i++) 可能会更耗时,把它改成 int i; for (i = 0 ; i < 10; i++) 也是降低代码运行时间的⼀种可考虑方式;

4.6 求最短路径的题目中以用 Dijkstra 解决的不要用 DFS 强行深搜(毕竟 DFS 也是⼀种暴力破解);

4.7 使用了 v.size()-1 等⽅式,如果v.size()本身就是0,因为 v.size() 返回值是无符号整数 unsigned int , unsigned int 的0减去1得到的是 unsigned int 的最⼤值而非 -1 ,这可能会让int i 循环时 i < v.size() - 1 超时;

4.8 明明可以用键值对找到对应的值(比如 bool visit[100] 寻找对应的 visit[80] 是否为 true ,复杂度为 O(1) )却用了 for 循环⼀个个找的存储⽅式(比如邻接矩阵可以⼀次查找得到,却用了邻接表⼀个个查找),以空间换时间的⽅式是常用降低算法时间复杂度的方式;

4.9 使用map 存储如果超时了,⽽题目又没有要求排序,换成用 unordered_map 就不会超时;同理,使用 set 存储如果超时了,可以考虑换成 unordered_set 避免超时。

05、有几个测试点答案错误

5.1 输出语句的错误。⽐如输出的个别字⺟不正确、输出 yes / no 的大小写没有按照要求、true / false 拼写错误、 1 后面单词单数不要加 s 、2 以上的个数后面单词复数要加 s 、除了单复数s还有be动词的 is 和 are 的区别等问题,有时候不正确的拼写遇上多条输出语句还会引起⼀半答案错误、⼀半答案正确的情况还始终找不到原因在哪;

5.2 switch 后⾯只能 int 或者 char 类型 其它类型不可以;

5.3 memset 只能赋值 0 、 -1 和最⼤值(因为 memest 函数是用按位赋值的),如果要给数组赋值⼀个特定的值,就要使用 fill 函数;

5.4 getline 读取的是⼀整行字符串,如果接下来还要读取字符 char ,会读取到上⼀行字符串末尾的回车换行符,所以为了避免这种情况,要在 getline(cin, s); 后面加⼀句 getchar(); 才能得到接下来自己想要读取到的 char ;

5.5 int + int 、 int * int 的过程中都有可能出现结果超过了 int 的值而产生溢出的情况,这样就会使⼀些数据较大的测试用例因为溢出变成了别的数字而得到答案错误;

5.6 有时候会给⼀组ab区间,但是a b并没有按照从⼩到大的方式输入,可能个别数据是 a > b ,所以要先判断⼀下给出的区间ab谁大谁⼩,如果a大b⼩就应该使用swap 函数交换⼀下;

5.7 如果是给id的题目,可能输出中要求按照不满4位在前面补 0 的情况,所以要用printf(“%04d”, a); 的方式输出,否则遇到不满4位的id输出结果可能会导致答案错误。

06、内存超限

内存超限是指开的数组或占用的内存过大,超过了要求的内存范围:

6.1 可以考虑开 vector 或者动态开辟数组的⽅式避免直接开 1000000 这样很大的数组;

6.2 如果是为了存储⼀些键值对,可以避免开 int hash[100000] 这样的大数组,⽽是用 map 或 者 unordered_map 来处理键值对的映射;

6.3 如果开大数组是为了存储稀疏矩阵,可以用邻接表存储的方式代替邻接矩阵来降低空间复杂度(以时间复杂度换空间复杂度的⽅式)。

07、提交第⼀次超时了,第二次却AC了

OJ系统⼤多有多台服务器,在平时练习过程中,提交那⼀瞬间如果遇到了新买的⾼配置服务器可能运行比较快,就能够让代码AC,有的时候遇上了普通或者慢的服务器,就有可能会运行超时。

08、浮点错误

程序中出现了除以 0 、取余 0 的这种非法操作:

8.1 可能出现了⼀个数除以 0 的情况;

8.2 可能出现了⼀个数取余 0 的情况;

8.3 发生了数据溢出而导致的除以 0 或者取余 0 的情况。

09、返回非零

9.1 如果用 C/C++ ,使用 int main 和 return 0;

9.2 如果⽤Java ,那么可能原因是代码里面的 public class 后免的那个名字不是 Main ,改成 Main 就可以通过了。

10、格式错误

10.1 可能是换行、空格等出现了问题,输出语句内可能有拼写错误、空格多打少打等情况;

10.2 行末的不必要的换行或是缺少了必要的换行也有可能引起格式错误;

10.3 题目要求小写/大写而自己没有按照题目要求输出也有可能格式错误;

10.4 题目要求输出4位数字不足前面添加 0 的时候没有按照要求用printf(“%04d”, a); 的方式输出,否则遇到不满4位的id输出结果可能会导致格式错误。

11、结尾语

以上就是岛主分享给大家的调bug经验总结,大家可以按照上述的格式将自己在刷题中积累的调试经验进行总结和归纳。相信经过坚持不懈的训练和总结,大家的机试水平会稳步提高,勇夺高分!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值