原题 [UVaoj 1586 molar-mass]
题目翻译
-
给出 T T T 个分子式 s s s ( 0 < ∣ s ∣ < 80 0<|s|<80 0<∣s∣<80 ),计算分子量
科普(对于化学小白): C , H , O , N C,H,O,N C,H,O,N 原子量分别为 12.01 , 1.008 , 16 , 14.01 12.01,1.008,16,14.01 12.01,1.008,16,14.01
样例输入 (想想为啥要给)
4
C
C6H5OH
NH2CH2COOH
C12H22O11
样例输出
12.010
94.108
75.070
342.296
题目分析
-
一开始的思路
- 读一个字母读一个数字,然后一乘,累加即可
-
看完样例后的思考
-
这题**好坑啊! -
这道题的几个坑:
- 有形如
C10
的分子量(即系数为多位数) - 有形容
C
的分子量(即系数为 1 1 1,忽略不写) - 输出保留 3 3 3 位小数
- 有形如
-
于是 ···
-
从第一位开始,找到字母后标记当前索引值 k k k
-
向后遍历,若 s [ i ] s[i] s[i] 为数字(即 ′ 0 ′ ≤ s [ i ] ≤ ′ 9 ′ '0' \leq s[i] \leq '9' ′0′≤s[i]≤′9′ ),在累加器 n n n 添加后添加一位 s [ i ] s[i] s[i]
科普(对于初学者):
- 在 n n n 后添加一位 m m m ,可参考以下代码:
n *= 10; n += m;
-
将一位数字符 c h ch ch 转换为数字( i n t int int )形式,可参考以下代码:
int ch_int = ch - '0';
-
若 s [ k + 1 ] s[k+1] s[k+1] 是字母,即 s [ k ] s[k] s[k] 系数为 1 1 1、忽略不写的情况,则默认
n = 1
-
将 n ⋅ g e t ( m ) n·get(m) n⋅get(m) 的结果加到答案 a n s ans ans 中 ( g e t ( m ) get(m) get(m) 指 m m m 的分子量)
-
遍历完字符串后,保留 3 3 3 位小数输出 a n s ans ans
科普:有关保留小数点输出的相关内容,详见 [c++保留小数_模 块的博客-CSDN博客]
-
-
AC代码
#include<iostream>
#include<iomanip>
#include<string.h>
using namespace std;
int main()
{
double mm[100]; // 存储分子的分子量
mm['C'] = 12.01;
mm['H'] = 1.008;
mm['O'] = 16;
mm['N'] = 14.01;
int T;
cin>>T;
while(T--)
{
string s;
cin>>s;
double ans = 0;
for(int i = 0; i < s.length(); )
{
int k = i, n = 0;
double m = mm[s[i]];
i++;
while((s[i] >= '0' && s[i] <= '9') && i < s.length())
{
n *= 10;
n += s[i] - '0';
i++;
}
i--;
if(i == k) n = 1;
ans += m * n;
i++;
}
cout<<fixed<<setprecision(3)<<ans<<endl;
}
return 0;
}