/* The plan 1. read the file into an array 2. read chemical formula from user 3. be able to search the table 4. work out total weight */ const bool debugging = false; #include #include #include using namespace std; struct element { string symbol, name; int atnumber; double atweight; }; // defined "element" as a new type of variable/constant void print(element X) { cout << X.symbol << "(\"" << X.name << "\", "; cout << X.atnumber << ", " << X.atweight << ")\n"; } void read(element & e, ifstream & f) { f >> e.symbol >> e.name >> e.atweight; } struct nicestream { string wholeline; int numtaken; int length; bool ended; }; char readchar(nicestream & ns) { char c; if (ns.numtaken >= ns.length) c = '\n'; else c = ns.wholeline[ns.numtaken]; ns.numtaken += 1; return c; } char sneakchar(const nicestream & ns) { return ns.wholeline[ns.numtaken]; } void unreadchar(nicestream & ns) { if (ns.numtaken > 0) ns.numtaken -= 1; } void refill(nicestream & ns) { getline(cin, ns.wholeline); if (cin.fail()) { ns.wholeline = "\n"; ns.ended = true; } else { ns.wholeline += '\n'; ns.ended = false; } ns.length = ns.wholeline.length(); ns.numtaken = 0; } bool ok(const nicestream & ns) { return ! ns.ended; } element search(string sy, element tab[], int max) { for (int i = 1; i <= max; i += 1) if (tab[i].symbol == sy) return tab[i]; tab[0].atnumber = 0; return tab[0]; } void prepare_file(ifstream & f, string fname) { f.open(fname.c_str()); if (f.fail()) { cout << "Can't open file '" << fname << "'\n"; exit(1); } } int read_table(ifstream & f, element ptable[]) { for (int atno = 1; atno < 150; atno += 1) { element e; read(e, f); if (f.fail()) return atno - 1; e.atnumber = atno; ptable[atno] = e; } } void checktable(element ptable[], int numels) { cout << "Finished reading " << numels << " elements\n"; if (debugging) for (int i = 1; i <= numels; i += 1) print(ptable[i]); if (debugging) { while (true) { cout << "type a symbol. "; string s; cin >> s; element x = search(s, ptable, numels); if (x.atnumber == 0) cout << "no such thing\n"; else print(x); } } } string read_symbol(nicestream & nin) { string symbol = ""; char c = readchar(nin); symbol += c; c = sneakchar(nin); if (c >= 'a' && c <= 'z') { c = readchar(nin); symbol += c; } return symbol; } int readnumber(nicestream & nin) { int num = 0; char c = readchar(nin); while (c >= '0' && c <= '9') { num = num * 10 + c - '0'; c = readchar(nin); } unreadchar(nin); return num; } double process_formula(nicestream & nin, element ptab[], int numels) { double total = 0.0, wt; char c; while (true) { c = sneakchar(nin); if (c >= 'A' && c <= 'Z') { string sym = read_symbol(nin); element e = search(sym, ptab, numels); if (e.atnumber == 0) { cout << "no such thing\n"; return 0.0; } wt = e.atweight; cout << " " << sym << ": " << wt; } else if (c == '(') { readchar(nin); wt = process_formula(nin, ptab, numels); cout << " (...): " << wt; } c = sneakchar(nin); if (c >= '0' && c <= '9') { int value = readnumber(nin); cout << " * " << value << " = " << wt*value; total += wt * value; } else total += wt; cout << "\n"; c = sneakchar(nin); if ((c < 'A' || c > 'Z') && c != '(') break; } if (c == '\n' || c == ')') { readchar(nin); return total; } else { readchar(nin); cout << "bad character '" << c << "'\n"; return 0.0; } } int main() { ifstream f; prepare_file(f, "/home/www/class/een118/atwt.txt"); element ptable[150]; int numels = read_table(f, ptable); f.close(); checktable(ptable, numels); nicestream nin; while (true) { cout << "formula: "; refill(nin); double molwt = process_formula(nin, ptable, numels); cout << "The molecular weight is " << molwt << "\n\n"; } /* type something like NaCl H2SO4 CaCO3 Ca(NO3)2 */ }