AI开发C语言应用按步走,表达式计算器calc的第二十步,魔法数修复、测试分隔符、位运算截断检查、进制溢出检查

calc20 --- 魔法数修复、测试分隔符、位运算截断检查、进制溢出检查

1. 概述

本次迭代从 suggestions.md 中选取了 4 个待改进项进行修复,涵盖代码质量、测试框架和运行时健壮性三个方面。

修复项

编号 问题 类型
C1 var_name[32] 魔法数 代码质量
G3 测试文件分隔符与表达式分隔符 ; 冲突 测试框架
G4 位运算截断 int 无警告 运行时健壮性
G5 进制数溢出无检查 运行时健壮性

2. 变更清单

文件 操作 说明
main.c 编辑 var_name[32]var_name[MAX_NAME](2 处)
test.expr 编辑 分隔符 ; → `````(反引号),避免与表达式分隔符 ; 冲突
Makefile 编辑 IFS=';'IFS='\'`
eval.c 编辑 新增 #include <limits.h> + check_int_trunc() 函数;6 处 (int) 转换前添加截断检查
parse.c 编辑 新增 #include <errno.h> + #include <stdio.h>;3 处 strtoul 后添加 errno == ERANGE 溢出检查

3. C1 --- var_name[32] 魔法数

3.1 改造前

c 复制代码
char var_name[32];

硬编码的 32,与 parse.hToken.name[32] 无显式关联。

3.2 改造后

c 复制代码
char var_name[MAX_NAME];

MAX_NAMEparse.h 中定义为 32,两处统一引用,修改一端时同步更新。

4. G3 --- 测试文件分隔符

4.1 问题

test.expr 使用 ; 作为字段分隔符,但 ; 现在也是合法的表达式分隔符(表达式分隔功能),导致 1;2;3 等表达式无法在测试文件中使用。

4.2 方案

将分隔符改为反引号 `````,原因:反引号在 calc 的词法分析器中永远为非法字符(TOKEN_ERROR),不会与任何合法表达式冲突。

文件 改动
test.expr ; → `````
Makefile IFS=';'IFS='\'`

同时保留了 ; 作为表达式分隔符的功能不变。

5. G4 --- 位运算截断检查

5.1 问题

eval.c 中位运算操作数先转为 int(32 位),超出 INT_MAX(2147483647)的值被静默截断,用户得不到提示。

5.2 方案

新增 check_int_trunc 函数,在 6 处 (int) 转换前调用:

c 复制代码
static int check_int_trunc(long double v)
{
    if (v > INT_MAX || v < INT_MIN) {
        fprintf(stderr, "  warning: value truncated to int\n");
        return 1;
    }
    return 0;
}

调用位置:parse_bitorparse_bitxorparse_bitandparse_shift(SHL/SHR)、parse_unary(BITNOT)。

6. G5 --- 进制数溢出检查

6.1 问题

parse.cstrtoul 解析十六进制/二进制/八进制数字时,超出 unsigned long 范围的值被静默截断为 ULONG_MAX,用户得不到提示。

6.2 方案

在每个 strtoul 调用前重置 errno = 0,调用后检查 errno == ERANGE

c 复制代码
errno = 0;
val = (long double)strtoul(input_pos, &end, 16);
if (errno == ERANGE)
    fprintf(stderr, "  warning: integer overflow\n");

7. 测试验证

bash 复制代码
$ make test
============================================
  calc --- 测试套件
============================================
  122 passed, 0 failed, 122 total
============================================

全部 122 个回归测试通过,功能不变,新增的检查仅在溢出/截断时输出警告,不影响正常计算结果。

相关推荐
冻柠檬飞冰走茶1 小时前
PTA基础编程题目集 7-11 分段计算居民水费(C语言实现)
c语言·开发语言·算法
An_s1 小时前
Java Spring Boot+vue3文件管理系统
java·开发语言
名字还没想好☜2 小时前
Go for-range 循环变量陷阱:goroutine 里全打印同一个值(Go 1.22 前后差异)
开发语言·后端·golang·go
倒流时光三十年2 小时前
第一阶段 05 · Java 客户端查询类详解(Query / SearchCriteria / Response 与复杂拼接)
java·开发语言·python
心平气和量大福大2 小时前
C#-WPF-控件-LiveChart图表-线性2(LineSeries)-数据绑定
开发语言·c#·wpf
lingran__2 小时前
C++_stack和queue和priority_queue(容器适配器)
开发语言·c++
::呵呵哒::2 小时前
java中SseEmitter
java·开发语言
星恒随风2 小时前
C++ 多态底层原理:静态绑定、动态绑定、虚函数表与工程实践
开发语言·c++·笔记·学习
wuyk5552 小时前
68.嵌入式 C 语言避坑指南:volatile 关键字 —— 单片机中断、寄存器访问的核心技巧
c语言·开发语言·stm32·单片机·嵌入式硬件