Skip to content

Instantly share code, notes, and snippets.

@ArthurSonzogni
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArthurSonzogni/8c9d24fc3b546d3cdc69 to your computer and use it in GitHub Desktop.
Save ArthurSonzogni/8c9d24fc3b546d3cdc69 to your computer and use it in GitHub Desktop.
Parse chemical expression (ie : (CH4)2HeLi )
#include <iostream>
#include <sstream>
typedef std::map<std::string,int> chemicalComposition;
void transferChemical(chemicalComposition& left, chemicalComposition& right)
{
for(chemicalComposition::iterator it = right.begin(); it!=right.end(); ++it)
left[it->first] += it->second;
right.clear();
}
chemicalComposition parseChemical(std::string formula)
{
chemicalComposition total;
chemicalComposition remainder;
size_t pos = 0;
while(formula.size() != 0)
{
if (isupper(formula[pos]) && isalpha(formula[pos])) // new element
{
// add previous remainder if there is one
transferChemical(total,remainder);
// read the name
std::string name;
name += formula[pos]; pos++;
while (pos<formula.size() && !isupper(formula[pos]) && isalpha(formula[pos])) { name += formula[pos]; pos++; }
remainder[name] = 1;
}
else if (isdigit(formula[pos])) // number
{
if (remainder.size() == 0)
throw std::invalid_argument("can't parse expression");
// read number
int multiplicity = 0;
while(pos<formula.size() && isdigit(formula[pos])) {multiplicity = 10*multiplicity + int(formula[pos] - '0') ; ++pos;}
// muliply remainder
for(chemicalComposition::iterator it = remainder.begin(); it!=remainder.end(); ++it) it->second *= multiplicity;
}
else if (formula[pos] == '(')
{
// add previous remainder if there is one
transferChemical(total,remainder);
// look for the right parenthesis
int left = pos;
++pos;
int count = 1;
while(pos<formula.size() && count!=0)
{
if (formula[pos] == '(')
++count;
else if (formula[pos] == ')')
--count;
++pos;
}
int right = pos;
if (pos==formula.size())
throw std::invalid_argument("can't parse expression");
remainder = parseChemical(formula.substr(left+1,right-left-2));
pos = right;
}
formula = formula.substr(pos);
pos = 0;
}
// add previous remainder if there is one
transferChemical(total,remainder);
return total;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment