|
> これで私の中での第1段階ができそうです。
第2段階はできたのでしょうか?
変数を増やすのは簡単ですが、その値を指定するのが面倒になりそうなので、
代入演算子を導入してみてはどうかと考えて、ちょっと書いてみました。
・変数は a〜z の 26個。
・「変数 = 式」の入力で変数に値を設定
・「式」の入力でその式の値を表示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int c; char *p, o[] = "= +-*/^ "; double x[26];
int get(void) { do c = *p++ & 0xff; while (isspace(c)); return c; }
double expr(const char *s)
{
double v;
if (*s == '=') {
char *q = p; int n = get();
v = (islower(n) && get() == '=') ? (x[n-'a'] = expr(s)) : (p = q, expr(s+2));
} else if (*s)
for (v = expr(s+2); c == s[0] || c == s[1]; )
switch (c) {
case '+': v += expr(s+2); break;
case '-': v -= expr(s+2); break;
case '*': v *= expr(s+2); break;
case '/': v /= expr(s+2); break;
case '^': v = pow(v, expr(s)); break;
}
else if (get() == '.' || isdigit(c)) v = strtod(p-1, &p), get();
else if (c == '(') v = expr(o), c == ')' ? get() : (c = 1);
else if (c == '-') v = -expr(s);
else if (c == '+') v = expr(s);
else if (!memcmp(p-1, "sqrt",4)) p += 3, v = sqrt(expr(s));
else if (!memcmp(p-1, "exp", 3)) p += 2, v = exp(expr(s));
else if (!memcmp(p-1, "log", 3)) p += 2, v = log(expr(s));
else if (!memcmp(p-1, "sin", 3)) p += 2, v = sin(expr(s));
else if (!memcmp(p-1, "cos", 3)) p += 2, v = cos(expr(s));
else if (!memcmp(p-1, "tan", 3)) p += 2, v = tan(expr(s));
else if (!memcmp(p-1, "atan",4)) p += 3, v = atan(expr(s));
else if (islower(c)) v = x[c-'a'], get();
else v = c = 1; /* error */
return v;
}
int main(void)
{
char buf[1024]; double v;
while (printf("> "), fgets(buf, sizeof buf, stdin) && *buf != '.') {
p = buf; v = expr(o);
if (c) puts(" error");
else {
p = buf;
if (!islower(get()) || get() != '=') printf(" %.15g\n", v);
}
}
return 0;
}
-----------------------------
実行例
> x = 5
> 2*x + 3
13
> y = 12
> sqrt(x^2 + y^2)
13
> exp(1)
2.71828182845905
> 4 * atan(1)
3.14159265358979
> .
|