AI开发C语言应用按步走,表达式计算器calc的第十一步,Token 联合体、哈希表满报错、批处理变量赋值

calc11 — Token 联合体、哈希表满报错、批处理变量赋值

1. 概述

本次迭代基于 suggestions.md 中的建议,完成了三项代码改进:

  1. Token 联合体— 将valuename字段合并为联合体,减少内存占用
  2. 哈希表满报错— 变量符号表满时输出错误提示,而非静默丢失
  3. 批处理变量赋值./calc "x = 5"现在可直接在批处理模式中赋值

2. 变更清单

文件操作说明
parse.h编辑Token 结构体改用联合体union { double value; char name[32]; } data;新增MAX_NAME 32
parse.c编辑tok.valuetok.data.valuetok.nametok.data.name
eval.c编辑t.valuet.data.valuet.namet.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 字节)

valuename共享同一块内存,type字段决定访问哪个成员。

3.3 涉及的文件

所有访问tok.value/t.valuetok.name/t.name的地方均改为tok.data.value/t.data.valuetok.data.name/t.data.name,涉及parse.ceval.c

4. 哈希表满报错

sym.csym_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/ └── calc

7. 测试验证

$maketest============================================calc — 测试套件============================================PASS[1](90-18)/3+15 →39... PASS[23]x=55PASS[24]y=1010...============================================29passed,0failed,29total============================================

批处理变量赋值测试通过:x=5输出5y=10输出10