- 小序号后加′∗′的是目前用的到且重要的。 其他感兴趣自行了解;
- 部分语法的错误,转c++可能会消失,如scanf中的取地址符&;c++更高效,尤其在字符串的处理,一般代码更短,相对更不易出错;
- 建议记录自己每次错误的原因;
一、 输入输出 (I/O) 篇
| 编号 |
错误类型 |
❌ 错误写法 (Example) |
✅ 正确写法 (Example) |
| 1* |
scanf 漏写取地址符 & |
int n; scanf("%d", n); |
int n; scanf("%d", &n); |
| 2* |
double 类型格式符混淆 |
double a; scanf("%f", &a); |
double a; scanf("%lf", &a); |
| 3 |
缓冲区残留 (混合 I/O) |
scanf("%d", &n); 紧接着 getline(cin, s); (导致 s 读到空行) |
scanf("%d", &n); getchar(); getline(cin, s); |
| 4 |
cin/cout 大数据超时 (TLE) |
默认使用 cin >> a; cout << a; |
ios::sync_with_stdio(false); cin.tie(0); |
| 5 |
多组数据未读完 |
只跑一次输入:cin >> n; |
while (cin >> n) { ... } 或 while (scanf(...) != EOF) { ... } |
二、 变量与数值运算篇
| 编号 |
错误类型 |
❌ 错误写法 (Example) |
✅ 正确写法 (Example) |
| 6* |
局部变量未初始化 |
int sum; for(...) sum += i; (sum 初始为垃圾值) |
int sum = 0; |
| 7* |
整型乘法溢出 |
long long ans = 100000 * 100000; (右侧先按 int 溢出)(在计算中超过了int的范围) |
long long ans = (long long)100000 * 100000; 或 1LL * a * b |
| 8* |
整数除法截断 |
double ans = 5 / 2; (结果为 2.0) |
double ans = 5.0 / 2; (结果为 2.5) |
| 9* |
浮点数直接比较相等 |
if (a == b) |
if (abs(a - b) < 1e-9) |
| 10* |
负数取模结果 |
int r = -5 % 3; (结果为 -2) |
int r = (-5 % 3 + 3) % 3; (结果为 1) |
| 11 |
位运算优先级 |
1 << 2 + 3; (被解析为 1 << (2 + 3)) |
(1 << 2) + 3; |
三、 数组与内存篇
| 编号 |
错误类型 |
❌ 错误写法 (Example) |
✅ 正确写法 (Example) |
| 12* |
数组越界访问 |
int a[10]; a[10] = 5; (最大下标是 9) |
检查边界,或开大数组如 int a[15]; |
| 13* |
大数组爆栈 (Stack Overflow) |
main 内定义 int a[1000000]; (消耗栈空间) |
将大数组定义为 全局变量 (使用堆/静态存储区) |
| 14 |
memset 赋值非 0/-1 |
memset(a, 1, sizeof(a)); (赋值成乱码值) |
fill(a, a + n, 1); 或 for 循环赋值 |
| 15* |
字符数组长度不足 |
char s[5]; 存入 "Hello" (需要 5+1 个位置) |
char s[6]; |
四、 逻辑与控制流篇
| 编号 |
错误类型 |
❌ 错误写法 (Example) |
✅ 正确写法 (Example) |
| 16* |
赋值与相等混淆 |
if (a = 1) (永远为真,且改变了 a 的值) |
if (a == 1) |
| 17* |
for 循环后加分号 |
for (int i = 0; i < n; i++); { /* 只执行一次 */ } |
移除分号 for (int i = 0; i < n; i++) { ... } |
| 18* |
多组数据未清空状态 |
循环中未清空全局 int cnt 或 vector<int> adj[] |
cnt = 0; 或 for(int i=0; i<n; i++) adj[i].clear(); |
| 19* |
逻辑与位运算混淆 |
if (a & b) 应该写成 if (a && b) |
逻辑运算用 && 和 &作用对象不同; |
| 20* |
负数逻辑错误 |
if (-1)会被判ture正确,运行if语句;只有if (0)会被判false非,不运行if语句; |
负数是ture;判false请用0; |
五、 C++ STL 与 特性篇
| 编号 |
错误类型 |
❌ 错误写法 (Example) |
✅ 正确写法 (Example) |
| 21 |
sort 比较函数 (cmp) 错误 |
bool cmp(a, b) { return a >= b; } (相等时返回 True 导致崩溃) |
bool cmp(a, b) { return a > b; } (严格弱序) |
| 22 |
map[] 自动创建新节点 |
if (mp[key]) (如果 key 不存在,会自动创建 key:0 的键值对) |
if (mp.count(key)) 或 if (mp.find(key) != mp.end()) |
| 23* |
vector.size() 无符号数陷阱 |
for (int i = 0; i <= v.size() - 1; i++) (v 为空时溢出) |
for (int i = 0; i < (int)v.size(); i++) |
| 24 |
STL 迭代器失效 |
遍历 vector 时 v.erase(it); 未更新 it |
it = v.erase(it); |
| 25 |
保留字命名冲突 |
变量名使用了 time、y1、next、rank 等 |
使用 my_time、_rank 或局部变量 (在 main 内部) |
六、养成好习惯可以避免许多错误:
- 定义变量时就赋值为零;
- 不在
main()函数内定义大数组;
- 数组可以开的比数据范围大些,可以避免越界。但须注意,开数组的时间复杂度和数组大小成正比,开太大也会超时;
- 关于爆
int,有邪修不推荐;邪修如下:
在头文件后面加上如下一行,会把你输入的int自动转化为long long型。注意int main()的int也会被转化,所以你需要换成signed mian()。
#include<stdio.h>
#define int long long
signed main(){
int x=0;//x为long long型;
}
不推荐原因,longlong毕竟比int需要多一倍的空间,虽然爆int的情况更多,但也纯在因为用longlong浪费时间空间,而被卡的情况;
推荐typedef long long ll;给long long起了个别名ll;仍自主判断是否需要开long long;
#include<stdio.h>
typedef long long ll;
int main(){
ll x=0;//x为long long型;
}