从C代码中使用bc

时间:2017-02-10 07:26:50

标签: yacc bc

我正在使用 lex yacc 编写表达式评估程序的代码,它可以执行以下操作:

/,*,+, - ,pow(a,b),sqrt(a),log(a)

表达式中也可以有括号。

输入表达式位于文件" calculator.input"

我必须将代码的时间与 bc 进行比较,我面临以下问题:

1)bc不接受 pow(a,b) log(a)而是接受 a ^ b l(a)。 我该如何更改?

2)如何使用 yacc 程序中主要功能的 bc ?或者那无法完成?

1 个答案:

答案 0 :(得分:0)

我认为更改代码比更改bc更容易,但如果您想尝试,可以在GNU project page上找到指向bc源代码包的链接并在FreeBSD source mirror。当然,最终结果不会严格地说是bc,所以我不知道为了你的任务,它是否仍然可以计算。

我不知道你应该实现的pow函数的规范是什么,但请注意bc的{​​{1}}运算符只允许整数指数,所以它可能不适用于所有测试用例(当然,除非所有测试用例都有整数指数。)您可以使用^计算a^b,但对于整数指数不会那么准确:< / p>

e(l(a)*b)

您可能需要咨询您的导师,教授或助教。

如果您不希望(或不允许)手动生成e(l(10)*100) 99999999999999999920085453156357924020916787698393558126052191252537\ 96016108317256511712576426623511.11829711443225035170 10^100 10000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000 等效测试用例,您可以使用bc自动执行该过程(如果是指数子表达式并不复杂),或者通过调整计算器以sed的语法输出表达式。后者将是一个相当容易的项目,你可能通过实现它来学习一些东西。

如果您使用的是类Unix系统,则可以从C程序轻松运行任何命令行实用程序。 (实际上,您也可以在非类Unix系统上执行此操作,但库函数会有所不同。)如果您不需要通过bc将数据传递给bc,则可以使用popen(3)库函数,这当然是最简单的解决方案。

否则,您必须设置一对pipe(2) s(一个用于写入stdin的{​​{1}},另一个用于从bc读取,fork(2)子进程,并使用其中一个exec*函数调用(可能是stdinstdout)在孩子中运行execlp(3)。 (在你写信给孩子的时候注意管道死锁。)一旦子进程完成(你会注意到,因为你将在管道上得到一个EOF,你用它来读取{{1您应该使用wait(3)execvp(3)来获取其状态代码。

如果所有这些看起来过于复杂,您可以使用从shell运行程序和bc的更简单的解决方案。 (您可以使用类似Unix的shell内置的stdout shell来获取执行时间的度量,尽管它不是微秒分辨率,这对于这样一个简单的程序可能是必需的。)