整理自我在騎魔滋事家哄騙小朋友的作業
話說有一陣子竟然變成月經題

這個程式可以處理像是
2+11.5*3
180+(9*12-6)

之類的算式
可處理括號和運算優先權,但不會處理syntax error和runtime error(例如div by 0)

轉載請註明出處
如果發現bug或有更好的改進意見,請讓我知道

// design by novus 2008
// some right reserved
#include <stdio.h>
#include <stdlib.h>

double Eval2(char *expr, char **end) {
    double Eval0(char*, char**);
    double res=0;
    if (*(*end=expr) == '(') {
        res = Eval0(*end+1, end);
    if (**end == ')') ++*end;
    } else { res=strtod(*end, end); }
    return res;
}

double Eval1(char* expr, char** end) {
    double res = Eval2(expr, end);
    while (**end=='*' || **end=='/')
        (**end=='*')? (res*=Eval2(*end+1, end)): (res/=Eval2(*end+1, end));
    return res;
}

double Eval0(char* expr, char** end) {
    double res = Eval1(expr, end);
    while (**end=='+' || **end=='-')
        res +=(**end=='+')? Eval1(*end+1, end): -Eval1(*end+1, end);
    return res;
}

int main() {
    char expr[128]={0}, *pos=0;
    printf("Exp : ");
    scanf("%s", expr);
    printf("Ans : %f\n", Eval0(expr, &pos));
}

//****** 2009-jun-06 ******

上面的程式可是純純正正的C++

因為有人抱怨欠缺C++味,所以另外推出C++風味餐

// design by novus 2009
// some right reserved
#include <iostream>
#include <cstdlib>

using namespace std;

double Eval2(istream& iss) {
    double Eval0(istream& iss);
    double res=0;
    if (iss.peek() == '(' && iss.get()) {
        res = Eval0(iss);
        iss.peek() == ')' && iss.get();
    } else { iss >> res; }
    return res;
}

double Eval1(istream& iss) {
    double res = Eval2(iss);
    while (iss.peek() == '*' || iss.peek() == '/')
        (iss.get() == '*')? (res*=Eval2(iss)): (res/=Eval2(iss));
    return res;
}

double Eval0(istream& iss) {
    double res = Eval1(iss);
    while (iss.peek() == '+' || iss.peek() == '-')
        res +=(iss.get() == '+')? Eval1(iss): -Eval1(iss);
    return res;
}

int main() {
    cout << Eval0(cin) << endl;
    system("pause");
}


novus 發表在 痞客邦 PIXNET 留言(6) 人氣()


留言列表 (6)

發表留言
  • mick
  • 這支程式

    這支程式太熱門了,
    我學生作業的版本原來是來自這裡啊....
    引用也沒通知一下....
  • 哇哈哈~~

    真的有人拿去交作業了

    抓到了當然是不用客氣啦

    (拿排版這麼難看的程式去交,不被盯上也難)

    novus 於 2008/12/13 14:16 回覆

  • damody
  • 這是C不是C++吧?

  • 這是C也是C++

    novus 於 2009/06/06 00:53 回覆

  • damody
  • 感謝指教!哈!
  • damody
  • 接上一留言,我找這個其實是最近想寫個畫微積分11章的奇怪3維函數圖形,但覺得自己的想法太簡單,想到其它地方取經剛好就到這來了,因為每次微積分老師都說,你們可以寫程式畫畫看,講n遍了想說快點在期未考時趕出來。
  • JasonHuang
  • 這個寫法實在是太神奇了!
    值得細細研究XD
    感謝 novus !~
  • 這其實是最基本的 recursive descent parsing,大概是手工刻語法解析器最簡單、也最普遍的做法。

    和堆疊轉後置式做法雖然有所不同,但本質上都是狀態機+堆疊。

    如果你有看到這則留言的話,不妨想想看,我的程式堆疊在哪裡

    novus 於 2015/04/30 20:43 回覆