C言語関係掲示板

過去ログ

No840 カッコのついた数式処理

[戻る] [ホームページ]
No.10726

Re:この課題を教えてください。
投稿者---かずま(2003/11/21 13:58:09)


掲示板に投稿する前に、【掲示板ご利用上の注意】ぐらいはちゃんと読みましょう。
投稿するときに、プログラムが左詰になるのがわかるはずですが、それを
変だとは思わないのでしょうか?

題名も内容を表さず不適切です。「カッコのついた数式処理」あるいは
「数式処理」だけでもかまわないでしょう。

プログラムもかなりいい加減ですね。

  10+3=  だと result = 4
  1 2+3= だと result = 15
  --7=   だと result = -7

全部書き直さないとだめなんでしょうが、最小限の修正で括弧が使えるように
してみました。

#include <stdio.h>

typedef enum { NUM, OP, END } STATE;

int result = 0, mresult = 0, num, sign;
char op = ' ', mop = ' ';

int stack[100], *sp = stack;

void push(int result, int mresult, char op, char mop)
{
    *sp++ = result;  *sp++ = mresult;  *sp++ = op;  *sp++ = mop;
}

void pop(int *result, int *mresult, char *op, char *mop)
{
    *mop = *--sp;  *op = *--sp;  *mresult = *--sp;  *result = *--sp;
}

void calcmul(void)
{
    switch (mop) {
    case ' ': mresult  = num*sign; break;
    case '*': mresult *= num*sign; break;
    case '/': mresult /= num*sign; break;
    }
}

void calc(void)
{
    calcmul();
    switch (op) {
    case ' ': result  = mresult; break;
    case '+': result += mresult; break;
    case '-': result -= mresult; break;
    }
    mresult = 0;
    mop = ' ';
}

int main(void)
{
    char c;
    STATE s = OP;
    while ((c = getchar()) != EOF) {
        switch (s) {
        case OP:
            if (c >= '0' && c <= '9') {
                num = c - '0';  sign = 1;  s = NUM;
            } else if (c == '-') {
                num = 0;  sign = -1;  s = NUM;
            } else if (c == '(') {
                push(result, mresult, op, mop);
                sign = 1, result = 0, mresult = 0, op = ' ', mop = ' ';
            }
            break;
        case NUM:
            if (c >= '0' && c <= '9') {
                num *= 10;  num += c - '0';
            } else if (c == '*' || c == '/') {
                calcmul();  mop = c;  s = OP;
            } else if (c == '+' || c == '-') {
                calc();  op = c;  s = OP;
            } else if (c == '=') {
                calc();  printf("result = %d\n",result);
                return 0;
            } else if (c == ')') {
                calc();
                num = result;
                sign = 1;
                pop(&result, &mresult, &op, &mop);
            }
            break;
        }
    }
    return 0;
}


No.10727

Re:この課題を教えてください。
投稿者---かずま(2003/11/21 14:02:54)


>    char c;
>    STATE s = OP;
>    while ((c = getchar()) != EOF) {
  
ここですが、char c; は int c; にするべきでしょう。


No.10728

Re:この課題を教えてください。
投稿者---popo(2003/11/21 16:19:38)


不躾ですみませんでした・・・。
プログラムもかなりいい加減だったそうで・・・。
ご教授ありがとう御座います。参考にさせて頂きます。

No.10730

Re:この課題を教えてください。
投稿者---たか(2003/11/21 21:06:42)


>不躾ですみませんでした・・・。
>プログラムもかなりいい加減だったそうで・・・。
>ご教授ありがとう御座います。参考にさせて頂きます。

わっかずま様よくできていますね。私の場合構造体を作って一度にpushdown
した所が違いますがそれ以外は同じですね。
入力部は確かにいい加減ですが課題に沿って解いてみました。

No.10732

Re:この課題を教えてください。
投稿者---あかま(2003/11/22 13:58:54)


>わっかずま様よくできていますね。私の場合構造体を作って一度にpushdown
>した所が違いますがそれ以外は同じですね。
ワタシの中ではかずまさんの↓これが伝説になってます。50行…
http://f1.aaa.livedoor.jp/~pointc/log695.html


No.10768

Re:この課題を教えてください。
投稿者---かずま(2003/11/24 18:06:59)


> ワタシの中ではかずまさんの↓これが伝説になってます。50行…

50行とは長すぎるなあと思ったら、べき乗、単項+、数学関数が入っている
ようですね。それらを削って、マクロを使って、30行にしてみました。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define C(c, op)  case c: v op expr(s+2); break

int c;  char buf[1024], *p, o[] = "+-*/^^";

int get(void) { do c = *p++ & 0xFF ; while (isspace(c)); return c; }

double expr(const char *s) {
    double v;
    if (*s)
        for (v = expr(s+2); c==s[0] || c==s[1]; )
            switch (c) { C('+',+=); C('-',-=); C('*',*=); C('/',/=);}
    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 (isalpha(c)) exit(0);
    else c = 1;
    return v;
}

int main(void) {
    double v;
    while (fgets(p = buf, sizeof buf, stdin))
        v = expr(o), printf(c ? "   error\n" : "   %.15g\n", v);
    return 0;
}


No.10770

Re:この課題を教えてください。
投稿者---かずま(2003/11/24 18:41:56)


> int c;  char buf[1024], *p, o[] = "+-*/^^";

訂正。
  int c;  char buf[1024], *p, o[] = "+-*/";