给出一种物质的分子式(不带括号,仅包含最多四种原子C、H、O、N),求分子量。已知C,H,O,N的原子量分别为12.01,1.008,16.00,14.01。
输入格式:一个整数T,后面跟T个分子式。
输出格式:每一行一个分子量,保留三位小数。
具体见https://cn.vjudge.net/problem/uva-1586
解析:本题有一个难点,就是如何处理两个字母相连以及以字母结尾的分子式的情况。我的办法是构造一个新string,把应该补1的地方都补上1。处理这个string就简单多了。
我的C++代码如下(提交的时候没有把cctype头文件写进去,isalpha函数竟然也能使用,不知道为什么哦...):
1 #include <iostream> 2 #include <string> 3 #include <cstdio> 4 using namespace std; 5 int main() //求分子量 6 { 7 const double m_c = 12.01, m_h = 1.008, m_o = 16.00, m_n = 14.01; 8 string mole; 9 int T; 10 cin >> T; 11 while (T--) 12 { 13 cin >> mole; 14 double signal = 0, M = 0; 15 string n, tem; 16 int index; 17 auto e = mole.end(); 18 for (auto b = mole.begin();b != e;++b)//负责给原分子式补上数字1,存入n中 19 { 20 n += *b; 21 if (e - b > 1 && isalpha(*b) && isalpha(*(b + 1)))n += ‘1‘;//如果一个字母后面紧跟一个字母,要在中间补个1 22 else if (e - b == 1 && isalpha(*b))n += ‘1‘;//原式最后一个字符若为字母,则补1 23 } 24 e = n.end(); 25 for (auto b = n.begin();b != e;++b) 26 { 27 if (isalpha(*b)) 28 { 29 switch (*b) 30 { 31 case ‘H‘:signal = m_h;break; 32 case ‘O‘:signal = m_o;break; 33 case ‘C‘:signal = m_c;break; 34 case ‘N‘:signal = m_n;break; 35 default:break; 36 } 37 } 38 else //当读到数字 39 { 40 int weishu = 0; //记录这个数字的位数,以便跳跃 41 tem = tem.assign(b, e); //tem为一个从位置b到这个字符串末尾的string 42 index = stoi(tem); //StringToInt,从tem的第一个字符开始读一个数字 43 int temp = index; 44 while (temp) 45 { 46 weishu++; 47 temp /= 10; 48 } 49 b += weishu - 1; //越到下一个字母之前,通过大for再递增b,到下一个字母 50 M += signal * index; 51 } 52 } 53 printf("%.3f\n", M); 54 } 55 return 0; 56 }