Problem p00259 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>

using namespace std;

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;

const int INFTY = 1 << 29;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

// a^b mod m
int powmod(int a, int b, int m) {
  if (b == 0)
    return 1;
  int x = powmod(a, b / 2, m);
  x = x * x % m;
  return b & 1 ? x * a % m : x;
}
int inv(int n, int m) { return powmod(n, m - 2, m); }

int expr(const string &s, int m, int &i);

int fact(const string &s, int m, int &i) {
  int n = s.size();
  if (s[i] == '(') {
    i++;
    int res = expr(s, m, i);
    i++;
    return res;
  }
  int res = 0;
  while (i < n && isdigit(s[i]))
    res = res * 10 + s[i++] - '0';
  return res;
}

int term(const string &s, int m, int &i) {
  int n = s.size();
  int res = fact(s, m, i);
  while (i < n) {
    int op = s[i];
    if (op != '*' && op != '/')
      break;
    int tmp = fact(s, m, ++i);
    if (op == '*')
      res = res * tmp % m;
    if (op == '/') {
      if (tmp == 0)
        throw "NG";
      res = res * inv(tmp, m) % m;
    }
  }
  return res;
}

int expr(const string &s, int m, int &i) {
  int n = s.size();
  int res = term(s, m, i);
  while (i < n) {
    int op = s[i];
    if (op != '+' && op != '-')
      break;
    int tmp = term(s, m, ++i);
    if (op == '+')
      res = (res + tmp) % m;
    if (op == '-')
      res = (res - tmp + m) % m;
  }
  return res;
}

int main() {
  for (int p; cin >> p, p;) {
    cin.ignore();
    string s;
    getline(cin, s);
    assert(s[0] == ' ');
    s.erase(remove(all(s), ' '), s.end());

    try {
      int i = 0;
      int res = expr(s, p, i);
      printf("%s = %d (mod %d)\n", s.c_str(), res, p);
    } catch (const char *) {
      puts("NG");
    }
  }

  return 0;
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>

using namespace std;

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;

const int INFTY = 1 << 29;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

// a^b mod m
int powmod(int a, int b, int m) {
  if (b == 0)
    return 1;
  int x = powmod(a, b / 2, m);
  x = x * x % m;
  return b & 1 ? x * a % m : x;
}
int inv(int n, int m) { return powmod(n, m - 2, m); }

int expr(const string &s, int m, int &i);

int fact(const string &s, int m, int &i) {
  int n = s.size();
  if (s[i] == '(') {
    i++;
    int res = expr(s, m, i);
    i++;
    return res;
  }
  int res = 0;
  while (i < n && isdigit(s[i]))
    res = res * 10 + s[i++] - '0';
  return res;
}

int term(const string &s, int m, int &i) {
  int n = s.size();
  int res = fact(s, m, i);
  while (i < n) {
    int op = s[i];
    if (op != '*' && op != '/')
      break;
    int tmp = fact(s, m, ++i);
    if (op == '*')
      res = res * tmp % m;
    if (op == '/') {
      if (tmp == 0)
        throw "NG";
      res = res * inv(tmp, m) % m;
    }
  }
  return res;
}

int expr(const string &s, int m, int &i) {
  int n = s.size();
  int res = term(s, m, i);
  while (i < n) {
    int op = s[i];
    if (op != '+' && op != '-')
      break;
    int tmp = term(s, m, ++i);
    if (op == '+')
      res = (res + tmp) % m;
    if (op == '-')
      res = (res - tmp + m) % m;
  }
  return res;
}

int main() {
  for (int p; cin >> p, p;) {
    cin.ignore();
    string s;
    getline(cin, s);
    // assert(s[0]==' ');
    s.erase(remove(all(s), ' '), s.end());

    try {
      int i = 0;
      int res = expr(s, p, i);
      printf("%s = %d (mod %d)\n", s.c_str(), res, p);
    } catch (const char *) {
      puts("NG");
    }
  }

  return 0;
}