DevCN
菜单
全部文章快讯开发科技深度热点

C语言输入校验:用 strtol 拒绝尾随字符和越界值

从文本中解析分钟数,检查数字格式、尾随字符、数值范围和业务上限,确保失败调用不会意外覆盖输出参数。


本节目标

从文本中解析分钟数,检查数字格式、尾随字符、数值范围和业务上限,确保失败调用不会意外覆盖输出参数。

环境与运行方法

准备支持 C17 的 Clang 或 GCC。保存为 lesson.c,执行 cc -std=c17 -Wall -Wextra -Werror lesson.c -o lesson,编译后执行 ./lesson。命令适用于 macOS/Linux;Windows 需要相应的 C 工具链。

核心思路

atoi 不便区分有效零与失败。strtol 提供结束指针,数值超范围时还会设置 errno。先完成全部验证,再写入调用者的输出参数,可以保留失败前的状态。

完整示例

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
bool parse_minutes(const char *text, int *out) {
    char *end;
    errno = 0;
    long value = strtol(text, &end, 10);
    if (end == text || *end != '\0' || errno == ERANGE || value < 0 || value > 1440)
        return false;
    *out = (int)value;
    return true;
}
int main(void) {
    const char *samples[] = {"45", "12x", "1441", ""};
    for (size_t i = 0; i < 4; ++i) {
        int minutes = -1;
        if (parse_minutes(samples[i], &minutes)) printf("ok=%d\n", minutes);
        else printf("invalid=%d\n", minutes);
    }
}

预期输出

ok=45
invalid=-1
invalid=-1
invalid=-1

逐步理解

每次转换前清零 errno,避免先前的错误影响本次判断。end==text 表示没有读取到数字,检查字符串终止符则保证 12x 不会被当作 12。范围限制使最后转成 int 的值处于安全的小范围。

本函数要求两个指针都有效,不接收 NULL。strtol 允许前导空白,本例却拒绝尾随空白;如果要接受两侧空白,需要主动增加规则,而不是依赖偶然的解析行为。

常见问题与边界

  • 只检查结果是否为零会拒绝合法零。
  • 忽略结束指针会接受部分解析。
  • 在检查前写入 out 会让失败也产生副作用。

动手练习

测试 "0"、"1440" 与 "45 "。

参考答案

前两项返回合法值;最后一项的结束字符为空格,因此失败,输出参数仍为原值。是否接受尾随空白应由业务契约决定。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。