Skip to content

函数、表达式与控制流

18 道历年代码题都可以拆成同一个外壳:输入通过参数进来,若干状态变量记录过程,分支和循环推进算法,最后通过 return 或输出参数交出结果。

你首先要会的不是 main,而是读懂题目给出的函数原型。

函数原型就是答题合同

以 2025·41 为例:

c
void calMulMax(int A[], int res[], int n);

它已经告诉你:

  • void:函数本身不返回一个值;
  • A[]:输入数组;
  • res[]:调用者已经准备好的输出数组,答案写进去;
  • n:两个数组的有效长度。

卷面上不要擅自改成 int *calMulMax(...),也不要重新 malloc 一个结果数组。函数签名照抄,是最便宜的正确性。

常见的三种交付方式:

c
int solve(int A[], int n);              /* 用 return 交付一个整数 */
void solve(int A[], int res[], int n);  /* 写入输出数组 */
int solve(Node *head, int *answer);     /* return 表示成败,*answer 写结果 */

状态变量必须有清楚的含义

408 代码短,变量不需要起很长的名字,但每一个都要能用一句话解释:

c
int best = A[0];    /* 已扫描部分的最大值 */
int count = 0;      /* 满足条件的元素个数 */
int i = 0;          /* 当前扫描下标 */

最危险的不是变量名短,而是未初始化

c
int sum;            /* 错:初值未知 */
for (int i = 0; i < n; i++) sum += A[i];

应写成:

c
int sum = 0;

最大值通常不能随手初始化为 0,因为数组可能全是负数:

c
int best = A[0];
for (int i = 1; i < n; i++)
    if (A[i] > best) best = A[i];

if:把题目的分类讨论原样翻译

条件表达式常用这几组运算符:

含义C 写法
相等、不等==!=
大小比较<<=>>=
并且、或者、取反&&、`
奇偶x % 2 == 0x % 2 != 0

注意 = 是赋值,== 才是比较:

c
if (count == 0) return -1;

当题意有互斥的三种情况,就用 if / else if / else,例如 BST 查找:

c
if (cur->data == K) {
    return cur->data;
} else if (cur->data < K) {
    cur = cur->right;
} else {
    cur = cur->left;
}

? ::两选一取值的紧凑写法

当分支只是「二选一地取一个值」,可用条件运算符压成一行:

c
int larger = (a > b) ? a : b;                 /* 取较大者 */
cur = (K < cur->data) ? cur->left : cur->right;  /* 向左还是向右下降 */

条件 ? 甲 : 乙:条件为真取甲,否则取乙。本专题骨架里出现的 ?: 都能原样还原成 if/else,两者判分完全等价——写不惯就用 if/else,不必勉强。

for:次数明确的数组扫描

c
for (int i = 0; i < n; i++) {
    /* 处理 A[i] */
}

这里有效下标是 0..n-1,所以条件是 i < n,不是 i <= n

反向扫描要特别小心起点和类型:

c
for (int i = n - 1; i >= 0; i--) {
    /* 处理 A[i] */
}

408 卷面直接用 int i 最稳。若写成无符号类型,i >= 0 永远为真,可能死循环。

while:结束位置由数据决定

链表和双指针通常不知道要走几次,更适合 while

c
while (p != NULL) {
    p = p->next;
}

区间两端向中间收缩:

c
while (low < high) {
    int temp = A[low];
    A[low] = A[high];
    A[high] = temp;
    low++;
    high--;
}

写循环前先说清楚三件事:初始位置、继续条件、每轮怎样逼近结束。三者少一个,就容易越界或死循环。

breakcontinuereturn

  • break:只结束当前一层循环;
  • continue:跳过本轮剩余语句;
  • return:立即结束整个函数。

找到了唯一答案时,直接 return 往往最清楚:

c
for (int i = 0; i < n; i++)
    if (A[i] == target) return i;
return -1;

若只是跳出内层循环,不能误用 return,否则函数后续的统计和输出都不会执行。

立即写:一次扫描求最大值

只修改 maxValue 函数。测试壳已经准备了数组 [3,-1,8,2,5,4],正确输出应为 8

完成后再试两组边界:只有一个元素;所有元素都是负数。

本篇卷面检查

  • 函数名、返回类型、参数是否照抄题面?
  • 所有计数器、累加器、最优值是否初始化?
  • 数组循环是 i < n,还是误写成 i <= n
  • 每条执行路径最终是否都有正确的 return
  • ===&&|| 是否写对?

下一篇:数组、下标与二维矩阵