AI开发C语言应用按步走,表达式计算器calc的第十九步,注释、表达式分隔符、long double 精度

calc19 --- 注释、表达式分隔符、long double 精度

1. 概述

本次迭代新增三项功能,并对全局数值类型进行了精度升级:

  1. 注释支持 --- # 开头到行尾的内容被忽略
  2. 表达式分隔符 --- ; 分隔多个表达式,返回最后一个的值
  3. long double 精度 --- 全局 double → long double,提升运算精度

2. 变更清单

文件 操作 说明
parse.h 编辑 新增 TOKEN_SEMICOLON;Token.value 类型 double → long double
parse.c 重写 # 注释跳过;; 解析为 TOKEN_SEMICOLON;strtold/strtoul 替换 strtod
eval.h 编辑 API 参数 double* → long double*;新增 eval_exprs 声明
eval.c 重写 全部 double → long double;fmod → fmodl;新增 eval_exprs 实现
sym.h 编辑 API 参数 double → long double
sym.c 编辑 SymEntry.value double → long double;%Lg
func.h 编辑 API 参数 double* → long double*
func.c 重写 args/val double → long double;sinl/cosl 等 l 后缀数学函数
main.c 重写 double → long double;%Lg;调用 eval_exprs 替代 eval_expr
test.expr 编辑 修复溢出测试值;新增 # 注释测试;修复 0b1010/0777 解析

3. 注释支持

在 parse_next 中,当遇到 # 时跳过直到行尾或字符串结束:

c 复制代码
if (*input_pos == '#') {
    while (*input_pos && *input_pos != '\n') { column++; input_pos++; }
    if (*input_pos == '\n') { line++; column = 1; input_pos++; }
    return parse_next();  /* 递归获取下一个 token */
}

示例:

复制代码
calc> 3 + 5 # 这是注释
  8

4. 表达式分隔符

4.1 新增 eval_exprs API

c 复制代码
int eval_exprs(const char *input, long double *result);

循环解析多个以 ; 分隔的表达式,返回最后一个的值:

c 复制代码
int eval_exprs(const char *input, long double *result)
{
    parse_init(input); eval_error = 0;
    long double val = 0.0;
    while (!eval_error) {
        val = parse_expr();
        if (eval_error) return 1;
        Token t = parse_peek();
        if (t.type == TOKEN_SEMICOLON) {
            parse_consume();
            continue;
        }
        if (t.type != TOKEN_END) {
            print_error_context(t.col);
            fprintf(stderr, "  error: unexpected token after expression\n");
            return 1;
        }
        break;
    }
    *result = val; return 0;
}

4.2 使用

bash 复制代码
$ ./build/calc "1; 2; 3"
3

4.3 默认切换

parse_and_eval 和 repl 均改为调用 eval_exprs,因此 ; 分隔符在所有模式下均可使用。

5. long double 精度升级

5.1 涉及范围

组件 类型变更 影响
Token 数值 double → long double 解析和存储
求值器 double → long double 全部运算
符号表 double → long double 变量值
函数表 double → long double 参数和返回值
主程序 double → long double 输出格式 %Lg

5.2 数学函数后缀

所有 <math.h> 函数调用改为 l 后缀版本:

函数 原版 long double 版
正弦 sin sinl
余弦 cos cosl
正切 tan tanl
平方根 sqrt sqrtl
幂运算 pow powl
取模 fmod fmodl
绝对值 fabs fabsl

5.3 精度提升

类型 尾数位数 十进制精度 最大值
double 53 bits ~15 位 ~1.79e308
long double 64 bits ~19 位 ~1.19e4932

6. 测试验证

bash 复制代码
$ make test
============================================
  calc --- 测试套件
============================================
  PASS  [ 1] (90-18)/3+15           → 39
  ...
  PASS  [30] 1e5000*1e5000          → error
  ...
  PASS  [61] 0b1010                 → 10
  PASS  [62] 0777                   → 511
  ...
  PASS  [122] 3+5 # comment          → 8
============================================
  122 passed, 0 failed, 122 total
============================================
相关推荐
落魄实习生15 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
茉莉玫瑰花茶15 小时前
GO [ 方法 ]
开发语言·后端·golang
狗凯之家源码网16 小时前
微博图床 PHP 系统搭建与实战应用指南
android·开发语言·php
乌暮17 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习
2601_9622186118 小时前
C语言中三种库的编译和使用方法
开发语言·c++
铅笔小新z18 小时前
【C语言】操作符
c语言
传奇开心果编程18 小时前
中庸、有容、破执:仓颉编程语言的中华智慧结晶——三重哲学境界思辨
开发语言·华为·开源·软件工程
jimy118 小时前
派生类重写基类虚函数(二):override的作用
开发语言·c++
_upupup18 小时前
异常(C++)
java·开发语言·jvm
霸道流氓气质18 小时前
ComfyUI 图像生成工作流完全指南:从节点编排到Java生产级图像生产实战
java·开发语言·人工智能