返回介绍

数学函数--Math

发布于 2025-02-24 22:44:39 字数 2571 浏览 0 评论 0 收藏 0

ANSI-C 定义了许多数学函数例如 sin() , sqrt() , exp() 等等。作为另一个继承的练习,我们将添加库函数使用一个单个 double 参数并且具有一个 double 结构到我们的计算器。

这些函数工作的就如同一元运算符一样。我们可以定义一个新的类型给节点给每个函数并且收集大多数功能从 MinusName 类,但是这里有一个更简单的方法。我们扩展 struct Namestruct Math 如下:

struct Math { struct Name _;
  double (* funct) (double);
};
#define funct(tree) (((struct Math *) left(tree)) -> funct)

额外的给函数名称用于输入和标识符给识别,我们存储像 sin() 的库函数的地址在符号表项中。

在初始化期间我们调用下面的函数来输入所有的函数描述到符号表中:

#include <math.h>

void initMath (void) {
  static const struct Math functions [] = {
    { &_Math, "sqrt", MATH, sqrt },
    ...
    0 };
  const struct Math * mp;

  for (mp = functions; mp -> _.name; ++ mp)
    install(mp);
}

一个函数调用是一个因子就好像使用一个减号标记一样。对于识别我们需要扩展我们的语法对因子:

factor : NUMBER
   | - factor
   | ...
   | MATH ( sum )

MATH 是公共标识符对所有函数输入通过 initMath() 。这个翻译到下面的附加 factor() 在识别器中:

static void * factor (void) {
  void * result;
  ...
  switch (token) {
    case MATH:
    {
      const struct Name * fp = symbol;

      if (scan(0) != '(')
        error("expecting (");
      scan(0);
      result = new(Math, fp, sum());
      if (token != ')')
        error("expecting )");
      break;
    }

symbol 首先包含符号表元素对一个函数例如 sin() 。我们保存这个指针并且构建表达式树对于函数参数通过调用 sum() 。然后我们使用 Math ,类型描述给函数,并且让 new() 构建下面的节点给表达式树:

我们让一个二元节点的左边只想符号表元素给函数并且我们附加参数树在右边。这个二元节点具有 Math 作为类型描述,也就是说,方法 doMath()freeMath() 将会被调用来分别执行和删除节点。

Math 节点仍然使用 mkBin() 构建,因为这个函数不关心指针的后代。 freeMath() ,然而,可能只会删除右子树:

static void freeMath (void * tree) {
  delete(right(tree));
  free(tree);
}

如果我们仔细看上图,我们可以看到一个 Math 节点的执行是非常容易的。 doMath() 需要调用存储在符号表中元素可以被访问的作为左后代二元节点从之被调用:

static double doMath (const void * tree) {
  double result = exec(right(tree));

  errno = 0;
  result = funct(tree)(result);
  if (errno)
    error("error in %s: %s",
      ((struct Math *) left(tree)) -> _.name,
      strerror(errno));
  return result;
}

唯一的问题是抓住数字错误通过检测 errno 变量在 ANSI-C 头文件 errno.h 中声明。这个完成了数学函数的实现给计算器。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文