AI开发C语言应用按步走,表达式计算器calc的第十一步,Token 联合体、哈希表满报错、批处理变量赋值
calc11 — Token 联合体、哈希表满报错、批处理变量赋值
1. 概述
本次迭代基于 suggestions.md 中的建议,完成了三项代码改进:
- Token 联合体— 将
value和name字段合并为联合体,减少内存占用 - 哈希表满报错— 变量符号表满时输出错误提示,而非静默丢失
- 批处理变量赋值—
./calc "x = 5"现在可直接在批处理模式中赋值
2. 变更清单
| 文件 | 操作 | 说明 |
|---|---|---|
parse.h | 编辑 | Token 结构体改用联合体union { double value; char name[32]; } data;新增MAX_NAME 32宏 |
parse.c | 编辑 | tok.value→tok.data.value,tok.name→tok.data.name |
eval.c | 编辑 | t.value→t.data.value,t.name→t.data.name |
sym.c | 编辑 | sym_set循环结束后添加满表报错"symbol table is full" |
main.c | 编辑 | parse_and_eval增加is_assignment检测,支持批处理变量赋值 |
test.expr | 编辑 | x=5/y=10从错误用例改为成功用例(退出码 0) |
3. Token 联合体
3.1 改造前
typedefstruct{TokenType type;doublevalue;// 每个 Token 占 8 字节intcol;charname[32];// 每个 Token 占 32 字节}Token;// 总计 48 字节3.2 改造后
#defineMAX_NAME32typedefstruct{TokenType type;intcol;union{doublevalue;// TOKEN_NUMBER 时使用charname[MAX_NAME];// TOKEN_IDENTIFIER 时使用}data;}Token;// 总计 40 字节(节省 8 字节)value和name共享同一块内存,type字段决定访问哪个成员。
3.3 涉及的文件
所有访问tok.value/t.value和tok.name/t.name的地方均改为tok.data.value/t.data.value和tok.data.name/t.data.name,涉及parse.c和eval.c。
4. 哈希表满报错
在sym.c的sym_set函数中,线性探测循环结束后添加:
/* 表满 */fprintf(stderr," error: symbol table is full, cannot set '%s'\n",name);此前sym_set在 256 个桶全满时静默返回,赋值丢失且无任何提示。
5. 批处理变量赋值
5.1 改造前
parse_and_eval仅支持普通表达式求值,./calc "x=5"报错退出。
5.2 改造后
parse_and_eval中调用is_assignment检测赋值模式:
staticintparse_and_eval(constchar*input){charvar_name[32];if(is_assignment(input,var_name,sizeof(var_name))){constchar*p=input;while(*p&&*p!='=')p++;constchar*rhs=p+1;while(*rhs&&isspace((unsignedchar)*rhs))rhs++;doubleresult;if(eval_expr(rhs,&result)!=0)return1;sym_set(var_name,result);printf("%g\n",result);return0;}doubleresult;if(eval_expr(input,&result)!=0)return1;printf("%g\n",result);return0;}5.3 使用示例
$ ./build/calc"x = 5 + 3"8注意:批处理模式每次调用是独立进程,变量表不跨进程持久化。链式变量引用(如y = x * 2)需在 REPL 会话中完成。
6. 目录结构
calc/ ├── Makefile ├── parse.h / parse.c # Token 联合体 ├── eval.h / eval.c ├── sym.h / sym.c # 哈希表满报错 ├── main.c # 批处理变量赋值 ├── test.expr # 29 个测试用例 ├── doc/ │ ├── readme.md │ ├── calc1.md ~ calc10.md │ └── calc11.md # 本次构建 └── build/ └── calc7. 测试验证
$maketest============================================calc — 测试套件============================================PASS[1](90-18)/3+15 →39... PASS[23]x=5→5PASS[24]y=10→10...============================================29passed,0failed,29total============================================批处理变量赋值测试通过:x=5输出5,y=10输出10。
