#include #include #include #include using namespace std; struct elreader { string line; int pos; }; void start(elreader & er, string s) { er.line = s + "_"; er.pos = 0; } char getnext(elreader & er) { if (er.pos >= er.line.length()) return '_'; char c = er.line[er.pos]; er.pos = er.pos + 1; return c; } char peeknext(const elreader & er) { if (er.pos >= er.line.length()) return '_'; return er.line[er.pos]; } string readsym(elreader & er) { string ans = ""; char c1 = getnext(er); if (isupper(c1)) { char c2 = peeknext(er); if (islower(c2)) { getnext(er); return ans + c1 + c2; } return ans + c1; } cout << "readsym doesn't understand \"" << c1 << "\"\n"; return "_"; } int readnum(elreader & er) { int value = 0; while (isdigit(peeknext(er))) { int dig = getnext(er); value = value * 10 + dig - '0'; } // could use digittoint() return value; } struct item { char type; string s; int i; }; item readpart(elreader & E) { item result; char c = peeknext(E); if (isdigit(c)) { result.type = 'N'; result.i = readnum(E); } else if (isalpha(c)) { result.type = 'S'; result.s = readsym(E); } else if (c == '_') result.type = c; else if (c == '(' || c == ')') { result.type = getnext(E); } else { cout << "Unexpected in formula: " << c << "\n"; result.type = 'X'; } return result; } struct element { string name, symbol; double atwt; int atno; }; element makeel(int an, string sy, string nm, double aw) { element x; x.atno = an; x.atwt = aw; x.symbol = sy; x.name = nm; return x; } void print(const element & x) { cout << x.atno << " " << x.name << " " << x.atwt << " " << x.symbol << "\n"; } int read_table(element T[], int max) { ifstream elfile("elements.txt"); if (elfile.fail()) { cerr << "could not open elements.txt\n"; return 0; } int num = 0; while (true) { string n, s; double a; elfile >> s >> n >> a; if (elfile.fail()) break; num = num + 1; if (num >= max) { cerr << "too many elements\n"; exit(1); } T[num] = makeel(num, s, n, a); } elfile.close(); cout << num << " elements read\n"; return num; } element find_sym(const string & sy, element T[], int Tsize) { int i = 1; while (i <= Tsize) { if (T[i].symbol == sy) return T[i]; i = i + 1; } return makeel(0, "Q", "Nosuchthingium", 0.0); } double process_formula(elreader & E, element ptable[], int num) { double total = 0, previous = 0; while (true) { item it = readpart(E); if (it.type == '_' || it.type == ')') return total; else if (it.type == '(') { double subwt = process_formula(E, ptable, num); total = total + subwt; previous = subwt; cout << " Total now " << total << "\n"; } else if (it.type == 'S') { string elem = it.s; cout << elem << " : "; element e = find_sym(elem, ptable, num); print(e); total = total + e.atwt; previous = e.atwt; cout << " Total now " << total << "\n"; } else if (it.type == 'N') { int n = it.i; cout << "number " << n << "\n"; total = total + previous * (n-1); previous = 0; cout << " Total now " << total << "\n"; } } } int main() { element ptable[150]; int num = read_table(ptable, 150); if (num < 80) { cerr << "not enough (" << num << ") elements\n"; exit(1); } while (true) { cout << "\n? "; string s; cin >> s; elreader E; start(E, s); double result = process_formula(E, ptable, num); cout << "\nTotal molecular weight is " << result << "\n"; } }