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.h 中 Token.name[32] 无显式关联。

3.2 改造后

c 复制代码
char var_name[MAX_NAME];

MAX_NAME 在 parse.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_bitor、parse_bitxor、parse_bitand、parse_shift(SHL/SHR)、parse_unary(BITNOT)。

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

6.1 问题

parse.c 中 strtoul 解析十六进制/二进制/八进制数字时,超出 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 个回归测试通过,功能不变,新增的检查仅在溢出/截断时输出警告,不影响正常计算结果。

相关推荐
Zwawa44 分钟前
用两个按键做一个OLED菜单:先把选择和执行分开
c语言·单片机·嵌入式
Evand J2 小时前
【MATLAB例程介绍】(17)永磁同步电机(PMSM)基于自适应无迹卡尔曼滤波(AUKF)的电流噪声在线估计。测量噪声协方差自适应与转速估计对比仿真
开发语言·matlab·卡尔曼滤波·无迹卡尔曼滤波·pmsm·电机滤波
BaiPeter3 小时前
ZPL文件预览
开发语言·c++
心仪久了会沦陷5 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
Severus_black8 小时前
【C++初阶】list使用及相关实现,思路顺滑流畅!
c语言·数据结构·c++·stl·list
噢,我明白了9 小时前
JAVA中的一些基础应用知识点
java·开发语言
时间的拾荒人10 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾10 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者11 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
旖旎夜光11 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习