此代码用于在C中实现一个简单的算术表达式计算器。字符串"1+1"
生成整数2
,"2+3*4"
生成14
,依此类推。运算符优先级得到尊重,并反映了C。子表达式可以用括号分组。
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static jmp_buf jmp;
static unsigned long parse(const char **const str, const unsigned l) {
unsigned long r;
if (isdigit(**str))
r = strtoul(*str, (char **)str, 0);
else switch (*(*str)++) {
case '+':
return +parse(str, 6);
case '-':
return -parse(str, 6);
case '~':
return ~parse(str, 6);
case '(':
r = parse(str, 0);
if (*(*str)++ == ')')
return r;
default:
longjmp(jmp, errno = EINVAL);
}
for (;;) {
switch (*(*str)++) {
case '*':
if (l <= 5)
r *= parse(str, 5);
break;
case '/':
if (l <= 5)
r /= parse(str, 5);
break;
case '%':
if (l <= 5)
r %= parse(str, 5);
break;
case '+':
if (l <= 4)
r += parse(str, 4);
break;
case '-':
if (l <= 4)
r -= parse(str, 4);
break;
case '<':
if (l <= 3)
r <<= parse(str, 3);
break;
case '>':
if (l <= 3)
r >>= parse(str, 3);
break;
case '&':
if (l <= 2)
r &= parse(str, 2);
break;
case '^':
if (l <= 1)
r ^= parse(str, 1);
break;
case '|':
if (l <= 0)
r |= parse(str, 0);
break;
default:
--*str;
return r;
}
}
}
int main(const int argc, const char **argv) {
while (*++argv) {
if (setjmp(jmp)) {
perror(*argv);
errno = 0;
} else if (printf("%lu\n", parse(&(const char *){*argv}, 0)) < 0)
return errno;
}
return 0;
}
代码只完成了一半。"2+3*4"
之类的表达式被正确解析,并按预期生成14
。但是,如果优先级较低的运算符跟在优先级较高的运算符后面,如"2*3+4"
,丢弃较高优先级运算符的最后操作数之后的所有内容。因此,表达式"2*3+4"
错误地导致6
,因为+4
由于某种原因被忽略了。它应该导致10
。我该如何修复这个bug?
注意:I already figured out how to perform this task,但我正在尝试找出如何做到这一点,而不为每个优先级定义一个新的函数。
1条答案
按热度按时间xqkwcwgp1#
原始代码有几个问题:
沿着一些优先级较低的改进:
/
、%
、<<
和>>
的无效操作数。此修订代码按预期工作: