简体   繁体   中英

How to use a string or a char vector (containing any chemical composition respectively formula) and calculate its molar mass?

I try to write a simple console application in C++ which can read any chemical formula and afterwards compute its molar mass, for example:

  • Na2CO3, or something like:
  • La0.6Sr0.4CoO3, or with brackets:
  • Fe(NO3)3

The problem is that I don't know in detail how I can deal with the input stream. I think that reading the input and storing it into a char vector may be in this case a better idea than utilizing a common string.

My very first idea was to check all elements (stored in a char vector), step by step: When there's no lowercase after a capital letter, then I have found eg an element like Carbon 'C' instead of "Co" (Cobalt) or "Cu" (Copper). Basically, I've tried with the methods isupper(...) , islower(...) or isalpha(...) .

// first idea, but it seems to be definitely the wrong way
// read input characters from char vector 
// check if element contains only one or two letters
// ... and convert them to a string, store them into a new vector
// ... finally, compute the molar mass elsewhere
// but how to deal with the numbers... ? 

for (unsigned int i = 0; i < char_vec.size()-1; i++)
{
    if (islower(char_vec[i]))
    {
        char arr[] = { char_vec[i - 1], char_vec[i] };
        string temp_arr(arr, sizeof(arr));
        element.push_back(temp_arr);
    }
    else if (isupper(char_vec[i]) && !islower(char_vec[i+1]))
    {
        char arrSec[] = { char_vec[i] };
        string temp_arrSec(arrSec, sizeof(arrSec));
        element.push_back(temp_arrSec);
    }
    else if (!isalpha(char_vec[i]) || char_vec[i] == '.')
    {
        char arrNum[] = { char_vec[i] };
        string temp_arrNum(arrNum, sizeof(arrNum));
        stoechiometr_num.push_back(temp_arrNum);
    }
}

I need a simple algorithm which can handle with letters and numbers. There also may be the possibility working with pointer, but currently I am not so familiar with this technique. Anyway I am open to that understanding in case someone would like to explain to me how I could use them here.

I would highly appreciate any support and of course some code snippets concerning this problem, since I am thinking for many days about it without progress… Please keep in mind that I am rather a beginner than an intermediate.

This problem is surely not for a beginner but I will try to give you some idea about how you can do that.

Assumption: I am not considering Isotopes case in which atomic mass can be different with same atomic number.

  1. Model it to real world.

    How will you solve that in real life?

    Say, if I give you Chemical formula: Fe(NO3)3 , What you will do is:

    1. Convert this to something like this:

       Total Mass => [1 of Fe] + [3 of NO3] => [1 of Fe] + [ 3 of [1 of N + 3 of O ] ] => 1 * Fe + 3 * (1 * N + 3 * O) 
    2. Then, you will search for individual masses of elements and then substitute them.

       Total Mass => 1 * 56 + 3 * (1 * 14 + 3 * 16) => 242 
  2. Now, come to programming.

    Trust me, you have to do the same in programming also.

    1. Convert your chemical formula to the form discussed above ie Convert Fe(NO3)3 to Fe*1+(N*1+O*3)*3 . I think this is the hardest part in this problem. But it can be done also by breaking down into steps.

      1. Check if all the elements have number after it. If not, then add "1" after it. For example, in this case, O has a number after it which is 3 . But Fe and N doesn't have it.

      After this step, your formula should change to Fe1(N1O3)3 .

      1. Now, Convert each number, say num of above formula to:

        1. *num+ If there is some element after current number.

        2. *num If you encountered ')' or end of formula after it.

        After this, your formula should change to Fe*1+(N*1+O*3)*3 .

    2. Now, your problem is to solve the above formula. There is a very easy algorithm for this. Please refer to: https://www.geeksforgeeks.org/expression-evaluation/ . In your case, your operands can be either a number (say 2 ) or an element (say Fe ). Your operators can be * and + . Parentheses can also be present.

For finding individual masses, you may maintain a std::map<std::string, int> containing element name as key and its mass as value .

Hope this helps a bit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM