基本情報技術者試験 整数式を受け取ってその値を返すプログラム

下記の問題のプログラムをCで実装しました。

基本情報技術者試験
平成30年度秋期
午後試験 問8 データ構造及びアルゴリズム 整数式の解析と計算

計算の途中の変数の状態を表示するようにしました。

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

void print_status(int *value, char *operator, int *priority, int op_cnt) {
  int i;

  printf("value:    ");
  for (i = 0; i < op_cnt + 1; i++) {
    printf("%d, ", value[i]);
  }
  printf("\n");

  printf("operator: ");
  for (i = 0; i < op_cnt; i++) {
    printf("%c, ", operator[i]);
  }
  printf("\n");

  printf("priority: ");
  for (i = 0; i < op_cnt; i++) {
    printf("%d, ", priority[i]);
  }
  printf("\n");

  printf("op_cnt: %d\n\n", op_cnt);
}

int compute(char expression[]) {
  char operator[100];
  int op_cnt, priority[100], value[100];
  char chr;
  int i, ip, nest;

  // 解析処理
  // 下記の変数が設定される
  // value[] 数値
  // operator[] 演算子
  // priority[] 演算子の実行の優先度
  // op_cnt 演算子の数
  op_cnt = 0;
  value[0] = 0;
  nest = 0;
  while (*expression) {
    chr = *expression;
    expression++;

    if (('0' <= chr) && (chr <= '9')) {
      value[op_cnt] = 10 * value[op_cnt] + atoi(&chr);
      continue;
    }

    if ((chr == '+') || (chr == '-') || (chr == '*') || (chr == '/')) {
      operator[op_cnt] = chr;
      if ((chr == '+') || (chr == '-')) {
        priority[op_cnt] = nest + 1;
      }
      else {
        priority[op_cnt] = nest + 2;
      }
      op_cnt++;
      value[op_cnt] = 0;
      continue;
    }

    if (chr == '(') {
      nest = nest + 10;
      continue;
    }

    if (chr == ')') {
      nest = nest - 10;
      continue;
    }
  }

  print_status(value, operator, priority, op_cnt);

  // 計算処理
  while (op_cnt > 0) {
    // 優先度が最も高い演算子のインデックスをipに入れる
    ip = 0;
    for (i = 1; i < op_cnt; i++) {
      if (priority[ip] < priority[i])
        ip = i;
    }

    chr = operator[ip];
    switch (chr) {
      case '+':
        value[ip] = value[ip] + value[ip + 1];
        break;
      case '-':
        value[ip] = value[ip] - value[ip + 1];
        break;
      case '*':
        value[ip] = value[ip] * value[ip + 1];
        break;
      case '/':
        value[ip] = value[ip] / value[ip + 1];
        break;
    }

    for (i = ip + 1; i < op_cnt; i++) {
      value[i] = value[i + 1];
      operator[i - 1] = operator[i];
      priority[i - 1] = priority[i];
    }

    op_cnt--;
    print_status(value, operator, priority, op_cnt);
  }

  return value[0];
}

int main(int argc, char *argv[]) {
  // 整数式を実行時引数として渡す
  printf("%d\n", compute(argv[1]));
  return 0;
}
$ ./compute_expression 2*(34-(5+67)/8)
value:    2, 34, 5, 67, 8, 
operator: *, -, +, /, 
priority: 2, 11, 21, 12, 
op_cnt: 4

value:    2, 34, 72, 8, 
operator: *, -, /, 
priority: 2, 11, 12, 
op_cnt: 3

value:    2, 34, 9, 
operator: *, -, 
priority: 2, 11, 
op_cnt: 2

value:    2, 25, 
operator: *, 
priority: 2, 
op_cnt: 1

value:    50, 
operator: 
priority: 
op_cnt: 0

50