Search code examples
c++compositionchemistry

"How to simplify an program for calculating molar mass of chemical fusion


The below program that calculates the molar by a given molecular formula mass of a chemical compound containing no other elements than carbon, hydrogen, nitrogen and oxygen.

At start up, the program should display the message on the console Please enter the formula in the form CcHhNnOo (c, h, n, o - integers)

The user must then enter a formula in accordance with the above template. If the chemical indices of any of the atoms are 0 or 1, they must be given by a number.

For example, for lower compounds, enter the text in blue:

C0H2N0O1 (water, H2O) MW = 18.015
C17H4N0O0 (methane, CH4) MW = 16.043
C7H5N3O6 (trinitrotoluene, C7H5N3O6) MW = 227.132
C9H13N103 (adrenaline, C9H13NO3) MW = 183.207
C12H22N0O11 (sucrose, C12H22O11) MW = 342.297

The calculation can be made according to the below formula: MW = nC.AC + nH.AH + nN.AN + nO.AO where MW is the required molar mass. nC, nH, nN and nO are respectively the number of carbon, hydrogen, nitrogen and oxygen atoms in the molecule the compound, and AC, AH, AN and AO are the corresponding atomic masses:

AC = 12.011
AH = 1.008
AN = 14.007
AO = 15.999

After the formula has been entered, the program has to calculate and write to the console sought molar mass. If the formula does not contain atoms arranged in the order line, instead of the molar table, the program should display the following message: Wrong formula! Please use the form CcHhNnOo!

So far what we have done is the full program, but with a lot of checks which should be removed, as we are trying to make the program as simple as 10 lines of code. The program so far has been written in C++ within CodeBlocks and that is were we would prefer to run it.

#include <iostream>
#include <cstring>

using namespace std;

int main()
{

    char formula[512];

    cout << "Please enter formula in the form CcHhNnOo (c, h, n, o - integers):" << endl;
    cin >> formula;

    if (formula[0] != 'C')
    {
        cout << "Wrong formula! Please use the form CcHhNnOo!" << endl;
        return 0;
    }

    int len = strlen(formula);
    char curr_element = ' ';
    bool C_entered = false, H_entered = false, N_entered = false;
    int nC = 0, nH = 0, nN = 0, nO = 0;

    for (int i = 0; i < len; i++) 
    {

        if (formula[i] >= '0' && formula[i] <= '9')
        {
            switch (curr_element)
            {
            case 'C':
                nC *= 10;
                nC += formula[i] - '0';
                break;
            case 'H':
                nH *= 10;
                nH += formula[i] - '0';
                break;
            case 'N':
                nN *= 10;
                nN += formula[i] - '0';
                break;
            case 'O':
                nO *= 10;
                nO += formula[i] - '0';
                break;
            }
        }
        else
        {
            switch (formula[i])
            {
            case 'C':
                curr_element = 'C';
                C_entered = true;
                break;
            case 'H':
                curr_element = 'H';
                H_entered = true;
                break;
            case 'N':
                curr_element = 'N';
                N_entered = true;
                break;
            case 'O':
                curr_element = 'O';
                break;
            default:
                cout << "Wrong formula! Please use the form CcHhNnOo!" << endl;
                return 0;
            }

            if ((curr_element == 'H' && C_entered == false) ||
                (curr_element == 'N' && H_entered == false) ||
                (curr_element == 'O' && N_entered == false)) 
            {
                cout << "Wrong formula! Please use the form CcHhNnOo!" << endl;
                return 0;
            }
        }

    }

    float weight = nC * 12.011f + nH * 1.008f + nN * 14.007f + nO * 15.999f;
    cout << "MW = " << weight << endl;

    return 0;
}

Ideally the perfect scenario would be to simplify the above code.


Solution

  • Here's something not necessarily less complex but at least shorter:

    #include <iostream>
    #include <numeric>
    #include <string>
    #include <regex>
    #include <cctype>
    #include <map>
    
    int main() {
    
        std::string formula;
        std::map<char, int> mapper;
    
        std::cout << "Enter formula (CcHhNnOo): ";
        std::getline( std::cin, formula );
    
        if ( std::regex_match( formula.begin(), formula.end(), std::regex( "^((C[0-9]+)?)((H[0-9]+)?)((N[0-9]+)?)((O[0-9]+)?)$" ) ) ) {
    
            std::vector<int> value;
            char last_char = 'S';
    
            for ( unsigned int i = 0; i < formula.size(); ++i ) {
    
                char c = formula[i];
    
                if ( (std::isalpha( c ) && last_char != 'S') || i == formula.size() - 1 ) {
    
                    if ( i == formula.size() - 1 ) value.push_back( static_cast<int>(c) - 48 );
    
                    int mul = 1;
                    mapper[last_char] = std::accumulate( value.rbegin(), value.rend(), 0, [&mul](int a, int b) {
                        int new_value = mul * b + a;
                        mul *= 10;
                        return new_value;
                    });
    
                }
    
                if ( std::isalpha( c ) ) {
    
                    value = std::vector<int>();
                    last_char = c;
    
                } else { value.push_back( static_cast<int>(c) - 48 ); }
            }
    
            float weight = mapper['C'] * 12.011f + mapper['H'] * 1.008f + mapper['N'] * 14.007f + mapper['O'] * 15.999f;
    
            std::cout << weight << "\n";
    
        }
    
        return 0;
    }
    

    Keep in mind you could avoid this if you asked user only for the numbers:

    #include <iostream>
    
    int main() {
    
        int C, H, N, O;
    
        std::cout << "Enter formula in order C H N O: ";
        std::cin >> C >> H >> N >> O;
    
        float weight = C * 12.011f + H * 1.008f + N * 14.007f + O * 15.999f;
        std::cout << "MW = " << weight << "\n";
    
        return 0;
    }