1. 程式人生 > >計算分子量

計算分子量

題目:計算分子量                   

純淨物都有一定的組成,可用一個相應的化學式來表示其組成成分。化學式是用元素符號表示物質組成及原子個數的式子。用化學符號表示物質分子的組成的化學式稱為分子式,它的含義是:組成該化合物的元素,各元素原子數之比,各元素原子的重量之和。

化學式可以表示物質的1個分子,以及組成分子的元素種類和原子數量,如果要表示某物質的幾個分子,可以在化學式前加上係數.標明該物質的分子數.如2個

氧分子可用2O2表示,四氧化三鐵可以用Fe3O4表示。

化學式的相對分子質量(簡稱分子量)化學式中各原子的原子量的總和,即同種元素的相對原子質量與其原子個數相乘,不同原子的相對原子質量相加。例如:CO2, 碳是12, 氧是16, 那麼CO2分子量就是12+16×2=44 。

已知各化學分子式用到的元素原子量如下:

 

N

C

O

Cl

S

H

Al

Ca

Zn

Na

14

12

16

35

32

2

27

40

65

23

計算各分子式的分子量。

【標準輸入】  

第一行: T     表示T個分子式。接下來有T行,每行是一個分子式。

【標準輸出】

對於每個分子式,輸出佔一行,一個整數,即對應的分子量。

【約束條件】

2≤T≤8  ,化學式的長度不超過38 

【 樣  例 】

 

標準輸入

標準輸出

4

CO2

H2Na2SO4

N(NO2)3

(NH4)2SO4

44

146

152

140

 

要求:1:不帶括號的分子式求解

      2:帶一層括號的分子式求解

進一步要求:帶一層括號的分子式求解     

 

#include<iostream>
#include<map>
#include<string>
#include<cstdio>
using namespace std;
map<string,int>mp;//儲存原子的相對原子質量
int jisuan(string a)
{
    map<string,int>mp_count;//儲存所有原子的個數
    int s=0;//儲存結果
    int len=a.length(),fenzishu=1;//儲存分子數
    if(isdigit(a[0]))//如果剛上來存在數字說明找到了這個分子的個數
            {
                fenzishu=a[0]-'0';
                if(isdigit(a[1]))
                fenzishu=fenzishu*10+a[1]-'0';
                }
    for(int i=0;i<len;i++)//開始遍歷化學式
    {
        if(isupper(a[i]))//如果 遇到一個大寫字母,說明發現一個新原子
        {
            string temp;//將這個新原子儲存下來
            temp=a[i];
            int yuanzishu=1;//儲存這個新原子的個數
            if((i+1)<len&&isdigit(a[i+1]))//如果大寫字母后面跟數字,說明找到了這個原子的個數
            {
                yuanzishu=a[i+1]-'0';
                if((i+2)<len&&isdigit(a[i+2]))
                yuanzishu=yuanzishu*10+a[i+2]-'0';
                }
            
            else if((i+1)<len&&islower(a[i+1]))//如果大寫字母后面跟小寫字母,將小寫字母儲存到元素名稱中
            {
                temp+=a[i+1];
                if((i+2)<len&&isdigit(a[i+2]))//如果大寫字母后面跟小寫字母再之後跟數字,說明找到了這個原子的個數
                {
                    yuanzishu=a[i+2]-'0';
                    if((i+3)<len&&isdigit(a[i+3]))
                    yuanzishu=yuanzishu*10+a[i+3]-'0';
                    
                    }
                
                
                }
            if(mp_count.count(temp)==0)//原子個數累加
            mp_count[temp]=yuanzishu;
            else
            mp_count[temp]+=yuanzishu;
            }
         else if(a[i]=='(')//如果遇到括號,對括號裡面的操作
         {
                string kuohao="";//儲存括號裡面的化學式
                int n=1,k=i;
                for(i=i+1;a[i]!=')';i++)
                if(a[i]=='(')
                  n++;
                for(i=k+1;n;i++)
                {
                    if(a[i+1]==')')
                      n--;
                    kuohao+=a[i];
                    }
                int fenzishu_kuohao=1;
                if(isdigit(a[i+1]))
                {
                    fenzishu_kuohao=a[i+1]-'0';
                    if(isdigit(a[i+2]))
                    fenzishu_kuohao=10*fenzishu_kuohao+a[i+2]-'0';
                    }
                
                s+=jisuan(kuohao)*fenzishu_kuohao;//使用遞迴計算括號裡面化學式的相對分子質量
                }
        }
     int jieguo_kuohaowai=0;//儲存括號外的相對分子質量
     map<string,int>::iterator it;
     for(it=mp.begin();it!=mp.end();it++)
     {
            if(mp_count.count(it->first))//找出化學式中存在的元素
            jieguo_kuohaowai+=mp[it->first]*mp_count[it->first];
            }
      s+=jieguo_kuohaowai*fenzishu;
      return s;
    }
int main()
{
    mp["N"]=14;
    mp["C"]=12;
    mp["O"]=16;
    mp["Cl"]=35;
    mp["S"]=32;
    mp["H"]=2;
    mp["Al"]=27;
    mp["Ca"]=40;
    mp["Zn"]=65;
    mp["Na"]=23;
    int t;
    cin>>t;
    while(t--)
    {
        string a="";
        cin>>a;
        cout<<jisuan(a)<<endl;
    }
    getchar();getchar();
    return 0;
    }

註釋
1.可實現多括號巢狀計算;
2.可實現下標為兩位數字的計算;
3.可實現計算分子數;
測試樣例:12Na12Al45(12S78(12Cl45H78(12H12)56)45)23結果為38898288

 

總結
1.map的基本操作函式:

     C++ maps是一種關聯式容器,包含“關鍵字/值”對

     begin()         返回指向map頭部的迭代器

     clear()        刪除所有元素

     count()         返回指定元素出現的次數       (使用count,返回的是被查詢元素的個數。如果有,返回1;否則,返回0。
                                                    注意,map中不存在相同元素,所以返回值只能是1或0。)

     empty()         如果map為空則返回true

     end()           返回指向map末尾的迭代器

     equal_range()   返回特殊條目的迭代器對

     erase()         刪除一個元素

     find()          查詢一個元素                  (使用find,返回的是被查詢元素的位置,沒有則返回map.end()。)

     get_allocator() 返回map的配置器

     insert()        插入元素

2.isdigit是計算機C(C++)語言中的一個函式,主要用於檢查其引數是否為十進位制數字字元。(標頭檔案<ctype.h>(C)<cctype>(C++) )

3.isupper是一個函式,可以用來判斷字元c是否為大寫英文字母。(標頭檔案<ctype.h>(C)<cctype>(C++) )

4.islower,計算機函式,檢查引數c是否為小寫英文字母。(標頭檔案<ctype.h>(C)<cctype>(C++) )