2018/12/15

a017: 五則運算

a017: 五則運算


// 底下這一行,是因為要用 getline(), 這個是 c++ 才有的,或是要告訴 gcc 說,這個是 gnu 額外提供給 c 的
#define _GNU_SOURCE
#include

char *buf;
char *express;

// peek() 不移動字元位置,只傳回指標目前所指的字元
char peek() {
    while (*express == ' ') ++express; // 一律略過空白字元
    return *express;
}

// 因為 peek() 會略過空白字元,這邊直接傳回指標所指的字元
char get() { return *(express++); }

// 把數字傳回去,因為數字是連續的,所以....
int number() {
    int result = get() - '0';
    while (peek() >= '0' && peek() <= '9') result = 10*result + (get() - '0');
    return result;
}

// factor() 可以看成『分解成 + - 的『項』,小括號內的話,視為一項
int expression(); // 要遞迴呼叫,所以得先定義方法
int factor() {
    if (peek() >= '0' && peek() <= '9') return number();
    else if (peek() == '(') { // 遇上括號,則再遞回呼叫 expression()
        get(); // '('
        int result = expression();
        get(); // ')'
        return result;
    }
    else if (peek() == '-') {
        get();
        return -factor();
    }
    return 0; // error
}

// term() 則將各項運算結合起來, 主要是以 * / % 為主
int term() {
    int result = factor();
    char p = peek();
    while (p == '*' || p == '/' || p == '%') {
        p = get();
        if (p == '*') result *= factor();
        else if (p == '/') result /= factor();
        else result %= factor();
        p = peek();
    }
    return result;
}

int expression() {
    int result = term(); // 先取得第一項
    while (peek() == '+' || peek() == '-') { // 如果遇到 + - 號的話,則運算下一項的結合
        if (get() == '+') result += term();
        else result -= term();
    }
    return result;
}

int main ()
{
  size_t n;
  while (getline(&buf, &n, stdin) >= 0) {
    express = buf;
    int result = expression();
    printf ("%d\n", result);
  }
  return 0;
}

0 意見: