会引起 Compile Error 的错误

由于这类错误过于简单,相信是个正常人都会修,故略写。

  • int main() 写为 int mian()

  • 写完 structclass 忘记写分号。

  • 数组开太大,(在 OJ 上)使用了不合法的函数(例如多线程),或者函数声明但未定义,会引起链接错误。

  • 使用 algorithm 中的 max 函数时,一个参数类型为 int 而另一个参数类型为 long long

    • 示例:

      printf("%lld\n", max(0, query(1, 1, n, l, r)); // query 返回 long long 类型
  • goto 的时候,跳过了一些局部变量的初始化。

-    `switch-case` 的时候,跳过了一些局部变量的初始化。

不会引起 Compile Error 但会引发 Warning 的错误

这类错误较难发现,但会在使用 -W{warningtype} 参数编译时被编译器指出,所以要多学会使用 -W{warningtype} 参数,常见的有 -Wall-Wextra-Wshadow 等。

  • 由于运算符优先级产生的错误。

    • 1 << 1 + 1 : 1 左移了 2,即该表达式返回的值是 4。
  • 不正确地使用 static 修饰符。
  • -1 >> 1 == 1
  • 赋值运算符和 == 不分。
    • 示例: cpp if (n = 1) puts("Yes"); else puts("No"); 无论 \(n\) 的值之前为多少,输出肯定是 Yes 。 Tips: 如果你的确是想在 if / while 直接用赋值运算符(比如 while (foo = bar) ),又不想收到 Warning,可以使用 双括号while ((foo = bar))
  • 使用 scanf 读入的时候没加取地址符 & 。更一般地,使用 scanfprintf 的时候参数类型与格式指定符不符。
  • 没有考虑数组下标出现负数的情况。
  • 同时使用位运算和逻辑运算符( == )并且未加括号(例如 (x>>j)&3==2 )。
  • int 字面量溢出,例如: long long x = 0x7f7f7f7f7f7f7f7f1<<62
  • 未初始化局部变量,导致局部变量被赋予垃圾初值。
  • 局部变量与全局变量重名,导致全局变量被意外覆盖。(开 -Wshadow 就可检查此类错误。)

既不会引起 Compile Error 也不会引发 Warning 的错误

这类错误无法被编译器发现,所以在调试时只能依靠你自己。

会导致 WA

  • 多组数据未清空数组。

  • 读入优化未判断负数。

  • 所用数据类型不够大导致溢出,即常见的“三年 OI 一场空,不开 long long 见祖宗”,意思是因为没有使用 long long (开 long long )导致大量丢分从而赛季作废。

  • 存图时,节点编号 0 开始,而题目给的边中两个端点的编号从 1 开始,读入的时候忘记 -1。

  • 大/小于号打错或打反。

  • 在执行 ios::sync_with_stdio(false); 后混用两种 IO,导致输入/输出错乱。

    • 可以参考这个例子。

      // 这个例子将说明,关闭与 stdio 的同步后,混用两种 IO 的后果
      // 建议单步运行来观察效果
      #include <cstdio>
      #include <iostream>
      int main() {
      std::ios::sync_with_stdio(false);
      // 关闭同步后,cin/cout 将使用独立缓冲区,而不是将输出同步至 scanf/printf
      // 的缓冲区,从而减少 IO 耗时
      std::cout << "a\n";
      // cout 下,使用'\n'换行时,内容会被缓冲而不会被立刻输出,应该使用 endl
      // 来换行并立刻刷新缓冲区
      printf("b\n");
      // printf 的 '\n' 会刷新 printf 的缓冲区,导致输出错位
      std::cout << "c\n";
      return 0; //程序结束时,cout 的缓冲区才会被输出
      }
    • 特别的,也不能在执行 ios::sync_with_stdio(false); 后使用 freopen

  • 由于宏的展开,且未加括号导致的错误:

    #define square(x) x* x
    printf("%d", square(2 + 2));

    该宏返回的值并非 \(4^2 = 16\) 而是 \(2+2\times 2+2 = 8\) 。

  • 哈希的时候没有使用 unsigned ,因为对负数的右移运算会在最高位补 1,详见 位运算

  • 没有删除调试信息。

  • 误加了 ;

    • 可以参考这个例子:

      /* clang-format off */
      while (1);
      printf("OI Wiki!\n");
  • 没有正确设置哨兵值。例如,平衡树的 0 节点。

  • 在类或结构体的构造函数中,使用 : 初始化变量,且变量声明顺序不符合初始化时候的依赖关系。因为成员变量的初始化顺序只与它们在类中声明的顺序有关,而与在初始化列表中的顺序无关。

  • 并查集合并集合时没有把两个元素的祖先合并:

f[a] = b;              //错误
f[find(a)] = find(b); // 正确

会导致 RE

  • 对整数除以 \(0\) 。

    • 对 \(0\) 求逆元。
  • 没删文件操作(某些 OJ)。

  • 排序时比较函数的错误 std::sort 要求比较函数是严格弱序: a<afalse ;若 a<btrue ,则 b<afalse ;若 a<btrueb<ctrue ,则 a<ctrue 。其中要特别注意第二点。 如果不满足上述要求,排序时很可能会 RE。 例如,编写莫队的奇偶性排序时,这样写是错误的:

    bool operator<(const int a, const int b) {
    if (block[a.l] == block[b.l])
    return (block[a.l] & 1) ^ (a.r < b.r);
    else
    return block[a.l] < block[b.l];

    上述代码中 (block[a.l]&1)^(a.r<b.r) 不满足严格弱序的要求 2。 改成这样就正确了。

    bool operator<(const int a, const int b) {
    if (block[a.l] == block[b.l])
    return (block[a.l] & 1) ? (a.r < b.r) : (a.r > b.r);
    else
    return block[a.l] < block[b.l];
  • 解引用空指针。

会导致 TLE

  • 分治未判边界导致死递归。

  • 死循环。

    • 循环变量重名。
    • 循环方向反了。
  • BFS 时不标记某个状态是否已访问过。

  • 使用宏展开编写 min/max

    这种做法虽然算不上是「错误」,但是这里还是要拎出来说一下。

    常见的写法是这样的:

    #define Min(x, y) ((x) < (y) ? (x) : (y))
    #define Max(x, y) ((x) > (y) ? (x) : (y))

    这样写虽然在正确性上没有问题,但是如果你直接对函数的返回值取 max,如 a = Max(func1(), func2()) ,而这个函数的运行时间较长,则会大大影响程序的性能,因为宏展开后是 a = func1() > func2() ? func1() : func2() 的形式,调用了三次函数,比正常的 max 函数多调用了一次。

    这种错误在初学者写线段树时尤为多见,会大大增加程序的运行时间,甚至直接影响代码的时间复杂度。例如这份错误代码:

    #define max(x, y) ((x) > (y) ? (x) : (y))
    
    int query(int t, int l, int r, int ql, int qr) {
    if (ql <= l && qr >= r) {
    ++ti[t]; // 记录结点访问次数方便测试
    return vi[t];
    } int mid = (l + r) >> 1;
    if (mid >= qr) {
    return query(lt(t), l, mid, ql, qr);
    }
    if (mid < ql) {
    return query(rt(t), mid + 1, r, ql, qr);
    }
    return max(query(lt(t), l, mid, ql, qr), query(rt(t), mid + 1, r, ql, qr));
    }

    会被卡到单次查询 \(\Theta(n)\) 导致 TLE。

  • 没删文件操作(某些 OJ)。

  • for (int i = 0; i < strlen(s); ++i) :在循环中重复执行复杂度非 \(O(1)\) 的函数。(严格来说,这可能会引起时间复杂度的改变。)

会导致 MLE

  • 数组过大。
  • STL 容器中插入了过多的元素。
    • 经常是在一个会向 STL 插入元素的循环中死循环了。
    • 也有可能被卡了。

未定义行为

  • 数组越界。上下都算。(多数是 RE。)

    • 未正确设置循环的初值导致访问了下标为 -1 的值。
    • 无向图边表未开 2 倍。
    • 线段树未开 4 倍空间。
    • 看错数据范围,少打一个零。
    • 错误预估了算法的空间复杂度。
    • 写线段树的时候, pushuppushdown 叶节点。
  • 解引用野指针。
    • 未初始化就解引用指针。
    • 指针指向的区域已经 freedelete

会导致常数过大

  • 定义模数的时候,使用了全局变量(如 int mod = 998244353 ,为方便编译器按常量处理,正确做法是 const int mod = 998244353 )。
  • 使用了不必要的递归(需要注意的是,尾递归不在此列)。
  • 将递归转化成迭代的时候,引入了大量额外运算。

只在程序在本地运行的时候造成影响的错误

  • 文件操作有可能会发生的错误:

    • 对拍时未清除文件指针即 fclose(fp) 就又令 fp = fopen() , 这会使得进程出现大量的文件野指针。
    • freopen() 中的文件名未加 .in / .out
  • 使用堆空间忘记 deletefree

OI 做题的常见错误的更多相关文章

  1. php求和为s的两个数字(多复制上面写的代码,有利于检查错误)(由浅入深,先写简单算法,做题的话够用就行)

    php求和为s的两个数字(多复制上面写的代码,有利于检查错误)(由浅入深,先写简单算法,做题的话够用就行) 一.总结 1.多复制上面写的代码,有利于检查错误 2.一层循环就解决了,前后两个指针,和大了 ...

  2. C语言初学者代码中的常见错误与瑕疵(5)

    问题: 素数 在世博园某信息通信馆中,游客可利用手机等终端参与互动小游戏,与虚拟人物Kr. Kong 进行猜数比赛. 当屏幕出现一个整数X时,若你能比Kr. Kong更快的发出最接近它的素数答案,你将 ...

  3. 初识JAVA(二)(送给Java和安卓初学者)----常见错误

    博主接着上篇的来讲哦,以后的更新中,博主会出一些练习题,有兴趣的可以做做然后吧代码粘贴到下面,大家可以一起研究学习,一起进步,本篇文章主要讲的是: 一.常见错误 二.连接上篇一起的训练 无论是什么方向 ...

  4. Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误

    嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...

  5. .Net常见错误

    常见错误 #1: 把引用当做值来用,或者反过来 C++ 和其他很多语言的程序员,习惯了给变量赋值的时候,要么赋单纯的值,要么是现有对象的引用.然而,在C# 中,是值还是引用,是由写这个对象的程序员决定 ...

  6. Python程序的常见错误(收集篇)

    关于Python Python是一门解释性的,面向对象的,并具有动态语义的高级编程语言.它高级的内置数据结构,结合其动态类型和动态绑定的特性,使得它在快速应用程序开发(Rapid Applicatio ...

  7. 一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)

    问题: 问题出处见 C语言初学者代码中的常见错误与瑕疵(5) . 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己 ...

  8. 分数的加减法——C语言初学者代码中的常见错误与瑕疵(12)

    前文链接:分数的加减法——C语言初学者代码中的常见错误与瑕疵(11) 重构 题目的修正 我抛弃了原题中“其中a, b, c, d是一个0-9的整数”这样的前提条件,因为这种限制毫无必要.只假设a, b ...

  9. 要心中有“数”——C语言初学者代码中的常见错误与瑕疵(8)

    在 C语言初学者代码中的常见错误与瑕疵(7) 中,我给出的重构代码中存在BUG.这个BUG是在飞鸟_Asuka网友指出“是不是时间复杂度比较大”,并说他“第一眼看到我就想把它当成一个数学问题来做”之后 ...

随机推荐

  1. Eating Everything Efficiently(反向dp)

    传送门 取最大值即可.用拓扑,dfs都可以实现 #include <bits/stdc++.h> using namespace std; const int maxn=500009; i ...

  2. Educational Codeforces Round 77 (Rated for Div. 2) C. Infinite Fence

    C. Infinite Fence 题目大意:给板子涂色,首先板子是顺序的,然后可以涂两种颜色,如果是r的倍数涂成红色,是b的倍数涂成蓝色, 连续的k个相同的颜色则不能完成任务,能完成任务则输出OBE ...

  3. Apache Hudi又双叕被国内顶级云服务提供商集成了!

    是的,最近国内云服务提供商腾讯云在其EMR-V2.2.0版本中优先集成了Hudi 0.5.1版本作为其云上的数据湖解决方案对外提供服务 Apache Hudi 在 HDFS 的数据集上提供了插入更新和 ...

  4. js中刷新页面的方式总结

    1.window.onload / document.onload 2.history.go(num): (1)num为参数,num为正表示前进几个页面,类似于history.forward(): ( ...

  5. Day_12【集合】扩展案例4_判断字符串每一个字符出现的次数

    分析以下需求,并用代码实现 1.利用键盘录入,输入一个字符串 2.统计该字符串中各个字符的数量(提示:字符不用排序) 3.如: 用户输入字符串 "If~you-want~to~change- ...

  6. 值得收藏的js原型详解

    从虚无到Object 起初,地是空虚混沌,渊面黑暗:这时候一切还是null 神说,要有原型,于是就有了prototype 原型从凭空产生,于是需要一个指向于null的特征,人们把这种特征叫做隐式原型, ...

  7. 【题解】[SCOI2015]小凸玩矩阵

    题目链接 思路:题目要求变相解答一下,求出是否有n-k个数,不大于当前求的第k个数 而每一行每一列只能有一个数,就可以得到一个二分图的思路,边上的权值就是第i行第j列这个数的值 对于答案就是第k大的数 ...

  8. PAT 1028 List Sorting (25分) 用char[],不要用string

    题目 Excel can sort records according to any column. Now you are supposed to imitate this function. In ...

  9. 系列13 docker asp.net core部署

    一.介绍   本篇完整介绍asp.net core web api如何部署到docker容器中,并通过外部访问web api服务.在编写完成dockerfile之后,可以通过docker [image ...

  10. scrapy框架简介与安装启动

    Scrapy 是一个专业的.高效的爬虫框架,它使用专业的 Twisted 包(基于事件驱动的网络引擎包)高效地处理网络通信,使用 lxml(专业的 XML 处理包).cssselect 高效地提取 H ...