В стандартной библиотеке C нет функции для вычисления арифметических c выражений. Вот быстрая и грязная реализация функции evald
для результата double
. Он поддерживает 5 классических двоичных операций +
, -
, *
, /
, %
и возведение в степень с ^
, обрабатывает любые глубины скобок, но требует больше работы для унарных +
и -
.
Легко преобразовать в целое число только арифмети c.
Вот код:
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
double evald(const char *s, char **endp) {
struct operand {
double val;
int op, prec;
} stack[4], *sp, x;
char *p;
for (sp = stack;;) {
if (*s == '(') {
x.val = evald(s + 1, &p);
s = p;
if (*s == ')')
s++;
} else {
x.val = strtod(s, &p);
s = p;
}
while (isspace((unsigned char)*s))
s++;
switch (x.op = *s++) {
case '^': x.prec = 3; break;
case '*':
case '/':
case '%': x.prec = 2; break;
case '+':
case '-': x.prec = 1; break;
default: x.prec = 0; x.op = 0; s--; break;
}
while (sp > stack && x.prec <= sp[-1].prec) {
switch ((--sp)->op) {
case '^': x.val = pow(sp->val, x.val); break;
case '*': x.val = sp->val * x.val; break;
case '/': x.val = sp->val / x.val; break;
case '%': x.val = fmod(sp->val, x.val); break;
case '+': x.val = sp->val + x.val; break;
case '-': x.val = sp->val - x.val; break;
}
}
if (!x.op) break;
*sp++ = x;
}
if (endp) *endp = (char *)s;
return x.val;
}
int main(int argc, char *argv[]) {
if (argc > 1) {
for (int i = 1; i < argc; i++) {
printf("%s -> %.17g\n", argv[i], evald(argv[i], NULL));
}
} else {
char buf[100];
for (;;) {
printf("eval> ");
fflush(stdout);
if (!fgets(buf, sizeof buf, stdin) || (buf[0] == 'q' && buf[1] == '\n'))
break;
printf(" -> %.17g\n", evald(buf, NULL));
}
}
return 0;
}