我正在使用 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 ?或者那无法完成?
答案 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*
函数调用(可能是stdin
或stdout
)在孩子中运行execlp(3)
。 (在你写信给孩子的时候注意管道死锁。)一旦子进程完成(你会注意到,因为你将在管道上得到一个EOF,你用它来读取{{1您应该使用wait(3)
或execvp(3)
来获取其状态代码。
如果所有这些看起来过于复杂,您可以使用从shell运行程序和bc
的更简单的解决方案。 (您可以使用类似Unix的shell内置的stdout
shell来获取执行时间的度量,尽管它不是微秒分辨率,这对于这样一个简单的程序可能是必需的。)