GDPU C语言 番外篇:从运算符到排序,新手避坑实战指南
1. 运算符优先级那些年我们踩过的坑刚学C语言那会儿我最头疼的就是运算符优先级问题。明明代码逻辑没问题运行结果却总是莫名其妙。后来才发现问题出在运算符的隐形规则上。比如下面这段代码int result 5 3 * 2;你觉得result的值是多少如果是11说明你已经掌握了优先级如果是16那可得好好看这部分了。C语言的运算符优先级就像数学里的先乘除后加减但更复杂。我总结了个顺口溜单目 算术 移位 关系 等号 位与 位异或 位或 逻辑与 逻辑或 赋值具体来说单目运算符!、、--等优先级最高接着是算术运算符*、/、%高于、-关系运算符、、、又高于等号运算符、!最后才是各种赋值操作实际编程时我强烈建议多用括号。比如// 模糊写法 if (a b c) // 清晰写法 if ((a b) c)2. 排序算法实战从冒泡到选择2.1 冒泡排序菜鸟的入门必修课记得第一次写冒泡排序我写出了这样的神逻辑for (int i 0; i n; i) { for (int j 0; j n; j) { if (a[j] a[j1]) { swap(a[j], a[j1]); } } }结果当然是数组越界崩溃。正确写法应该是for (int i 0; i n-1; i) { for (int j 0; j n-1-i; j) { if (a[j] a[j1]) { int temp a[j]; a[j] a[j1]; a[j1] temp; } } }这里有两个关键点外层循环只需n-1次因为n-1轮后最后一个元素自然有序内层循环范围随轮数减少因为每轮都会把当前最大值冒泡到最后2.2 选择排序效率的小提升选择排序比冒泡稍高效因为它减少了交换次数。但新手常犯的错误是for (int i 0; i n; i) { int min a[i]; // 错误应该记录下标而非值 for (int j i1; j n; j) { if (a[j] min) { min a[j]; } } // 缺少交换操作 }正确的姿势应该是for (int i 0; i n-1; i) { int min_idx i; for (int j i1; j n; j) { if (a[j] a[min_idx]) { min_idx j; } } if (min_idx ! i) { int temp a[i]; a[i] a[min_idx]; a[min_idx] temp; } }3. 经典题目精讲水仙花数与斐波那契3.1 水仙花数的坑水仙花数三位数各位立方和等于自身看似简单但新手常犯两个错误错误处理数字位数int a i / 100; // 百位 int b i / 10 % 10; // 十位 int c i % 10; // 个位混淆和if (i a*a*a b*b*b c*c*c) // 错误应该是3.2 斐波那契的递归陷阱斐波那契数列的递归实现虽然优雅但直接套公式会掉坑long long fib(int n) { if (n 0) return -1; if (n 1) return 0; // 注意题目要求第一项是0 if (n 2) return 1; return fib(n-1) fib(n-2); }这里特别要注意题目要求的数列起始项可能和常规定义不同递归解法时间复杂度是O(2^n)对于大数会非常慢4. 调试技巧我的救命稻草初学阶段我总结了几条调试铁律打印大法好在关键位置插入printfprintf(调试信息i%d, a[i]%d\n, i, a[i]);边界检查数组操作前先检查下标if (index 0 index array_size) { // 安全操作 }逐步缩小法注释掉部分代码逐步定位问题橡皮鸭调试向没有编程背景的人解释你的代码逻辑记得有次调试三小时最后发现是把写成了。从此我养成了写比较表达式时把常量放前面的习惯if (5 x) // 这样写如果漏写号会报错5. 代码优化从能跑到高效当你的代码能正确运行后可以考虑这些优化减少循环次数// 优化前 for (int i 0; i strlen(s); i) // 优化后 int len strlen(s); for (int i 0; i len; i)用位运算代替乘除x x * 2; → x x 1; x x / 2; → x x 1;避免重复计算// 优化前 area 3.14159 * r * r; // 优化后 const double PI 3.14159; area PI * r * r;这些技巧在我完成课设时帮了大忙特别是处理大数据量时效率提升非常明显。

相关新闻