AOJ 1244 Molecular Formula

問題

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1244
元素記号と原子量の対応表と化学式が与えられる.化学式が何molか求める.
未知の元素が含まれていたら "UNKNOWN" と出力する.

解法

UNKNOWNな元素に出会ったときに例外を投げています. 化学式の末尾に到達しうるのはatom()num()なので,そこで終了判定しています.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <map>

using namespace std;

string str;
unsigned int p;
map<string,int> tbl;

bool isopen(int p){
    return str[p] == '(';
}

bool isclose(int p){
    return str[p] == ')';
}

int isdig(int p){
    return isdigit(str[p]);
}

int num(){
    int n = 0;
    while(p < str.size() && isdig(p)){
        n*=10;
        n+=str[p++] - '0';
    }
    return n;
}

int atom(){
    if(p == str.size()) return 0;
    string atm = "XXX";
    if(p+1 < str.size() && isupper(str[p]) && islower(str[p+1])){
        atm = string(str,p,2);
        p+=2; // jump Aa
    } else if(isupper(str[p])){
        atm = string(str,p,1);
        p++;  // jump A
    }
    if(tbl.count(atm) == 0){
        throw "";
    }
    return tbl[atm];
}

int mol(){
    int m;
    if(isclose(p)){
        return 0;
    }else if(isopen(p)){
        p++; // jump (
        m = mol();
        p++; // jump )
        m *= num();
        m += mol();
    } else {
        m = atom();
        if(m == 0) return 0;
        if(isdig(p)) m *= num();
        m += mol();
    }
    
    return m;
}

int main(){
    string atm;
    while(cin >> atm, atm != "END_OF_FIRST_PART"){
        cin >> tbl[atm];
    }
    while(cin >> str, str != "0"){
        p=0;
        try{
            cout << mol() << endl;
        } catch(const char* c){
            cout << "UNKNOWN" << endl;
        }
    }
}