分子量 (Molar Mass,ACM/ICPC Seoul 2005,UVa1586)
习题 3-3 分子量 (Molar Mass,ACM/ICPC Seoul 2005,UVa1586)
给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分别为C,H,O,N,原子量分别为12.01,1.008,16.00,14.01(单位:g/mol)。例如,C6H5OH的分子量为94.108g/mol。
【我的思路:】
首先设想会有哪些情况,然后去分析每种情况怎么解决,比如:
问题一:字母+字母
CHO怎么判断,怎么计算?
问题二:字母+数字
C,C1,C2这三个会不会都不一样,怎么判断?
问题三:字母+多位数字
C6,C66,C666怎么判断?
问题四:数字+字母
C6H,O2O怎么判断?
根据上面这四种情况来整理思路,一个一个解决,然后将相似的归类,最后整合,编程到一个程序中去。
【代码详解:】【源代码在文章最后】
最最开头,我们是需要头文件的。
#include "stdio.h"//不能少的
#include "string.h"//主要有一个求字符串长度的函数
#include "ctype.h"//这里需要用到几个函数,一个用来判断是否为大写字母,还有一个用来判断是否为数字
接下来首先,我们要来定义数组,需要哪些数组,我们需要记录C,H,O,N中的单分子的摩尔质量分别是多少,要用到“实型数组” double w[] 来存放。
然后,我们需要输入字符串啊,当然要一个“字符型数组” char s[] 。
这里在定义数组的时候要注意,为了有足够的空间放字符串,用2^8个空间,也就是256,别问为什么,因为我喜欢。其实也就是为了稍微大点的空间来存放。当然,还要考虑到那四个元素的ASCII码最高是多少,为了减少思考,就不用2^7=128了,因为房间刚刚好显得憋屈,所以用大一号的空间。还有,我的习惯是超过100的数组我就会放在主函数外面定义,防止空间过大导致运行的时候异常退出。
char s[];//记录分子串
double w[];//存放单个分子量
接下来进入主函数
int main()
{
这里要将C,H,O,N的摩尔质量存放到w[256]的数组中去。
w['C']=12.01,w['H']=1.008,w['O']=16.00,w['N']=14.01;//大写的分子的物质的量
接下来就要开始循环了,有些临时用的数据可以在循环体中定义,不用在外面定义占空间。
while(scanf("%s",s)==)
{//需要判断单个字母和多个数字的情况
这时候要想到,上面的这种写法是只要有输入就不会停止的,也就是说可以不断判断字符串的,那么每次开始的时候,需要将分子量的和sum清零。还要有暂时存放分子量的变量t,其次就是要有记录连续数字的一个整型变量cnt。对了,还有字符串的长度n,可以通过strlen()函数来取得。
double sum=;//每组分子串的开始时候分子量清零
double t=;//用来暂存单个分子量的和
int cnt=;//用来记录连续数字字符的值 ——即分子个数
int n=strlen(s);//记录分子串长度
接下来就要从字符串头开始循环到结尾来查找对应的是字母还是数字。
for(int i=;i<n;i++)
{
然后为了方便简写代码,就把s[i]存放到字符型变量cun中,放入单个字符。
char cun=s[i];//单个字符暂时存放在c中
既然刚刚已经记录了单个字符,那么这个字符是什么呢?接下来我们就要来判断什么字符,首先从简单地来判断,如果是字母怎么办?那么就把对应的分子量加上,并且放到sum中去。
if(isupper(cun))//是单个大写字母
{
t=w[cun];//把字母的数值代入临时分子量的和
sum+=t; //累加字母字符对应的分子量
}
好了,这样一来“问题一”就解决了,遇到字母就加上。
接下来就开始复杂的数字情况,为什么复杂,因为有单个数字的情况,有多个数字的情况,而且这个“多个”还不一定是两个。那么就开始分析数字的情况。
如果遇到数字了,那么说明前一个字母后面是有数字的,不管他是多少,都要把刚刚加上的单个分子量减掉,防止后面赋值多余,这个时候就体现了临时分子量t的作用了。
减掉之后,看看当前这个数字是多少,用上cnt存放cun-'0',当读取到这是数字之后,那就一鼓作气看看后面到底还有多少数字。
开始一个while小循环,如果后一个s[i+1]也是数字,那么就把当前的数字乘十加上后面那个数字,这里的后一个数字没有记录过,也没有变量储存,只有直接引用 s[i+]-'' ,然后i++继续往后找,直到后一个不是数字为止。
这里的i的作用除了小循环,还有让for循环中不在重蹈覆辙,判断过得就不要管了。
然后得到了最后的数字,存放在cnt中,这时候就要把临时分子量t中的数值乘上分子个数cnt,得到这个多分子的分子量sum,并且累加上去,这就是前面减去单个分子量的作用,防止这里的赋值多余。
if(isdigit(cun))//这个是数字的情况
{//需要进一步判断是否为多位数字
sum-=t;//先减去前一个所加的单个分子量,方便后面整体加上
cnt=cun-'';//读取数字字符的值
while(isdigit(s[i+]))//判断后一个字符是否为数字字符
{
cnt*=;//当前读取的数字乘十
cnt+=s[i+]-'';//在加上后一个数字当作个位
i++;//小循环中判断连续的数字字符 ,让下一个for循环不在重复循环已经判断过的连续数字
}
sum+=t*(cnt);//单个分子量t乘上分子个数cnt
}
好了,到这里判断比较复杂的数字情况也结束了,这就解决了字母+数字的“问题二”和“问题三”。
这个时候for循环也可以结束了。
}
for循环结束之后要输出最后结果,格式要固定好,摩尔质量中小数位数最多的是3位,那么结果也设置成3位实型 "%.3lf" 。
printf("%.3lf\n",sum);
这时候while循环整体也可以结束了,最后还要 return ; 然后程序结束。
}
return ;
}
源代码://应该是AC码,各位大神可以亲测一下,如果是的话希望支持一下。
#include "stdio.h"
#include "string.h"
#include "ctype.h"
char s[];//记录分子串
double w[];//存放单个分子量 int main()
{
w['C']=12.01,w['H']=1.008,w['O']=16.00,w['N']=14.01;//大写的分子的物质的量
while(scanf("%s",s)==)
{//需要判断单个字母和多个数字的情况
double sum=;//每组分子串的开始时候分子量清零
double t=;//用来暂存单个分子量的和
int cnt=;//用来记录连续数字字符的值 ——即分子个数
int n=strlen(s);//记录分子串长度
for(int i=;i<n;i++)
{
char cun=s[i];//单个字符暂时存放在c中
if(isupper(cun))//是单个大写字母
{
t=w[cun];//把字母的数值代入临时分子量的和
sum+=t; //累加字母字符对应的分子量
}
if(isdigit(cun))//这个是数字的情况
{//需要进一步判断是否为多位数字
sum-=t;//先减去前一个所加的单个分子量,方便后面整体加上
cnt=cun-'';//读取数字字符的值
while(isdigit(s[i+]))//判断后一个字符是否为数字字符
{
cnt*=;//当前读取的数字乘十
cnt+=s[i+]-'';//在加上后一个数字当作个位
i++;//小循环中判断连续的数字字符 ,让下一个for循环不在重复循环已经判断过的连续数字
}
sum+=t*(cnt);//单个分子量t乘上分子个数cnt
}
}
printf("%.3lf\n",sum);
}
return ;
}
作为初学者的我在经过两天的头疼之后写出来的,第一天用的方法比较繁琐,放弃了。第二天一天时间,最后在浴室想出了解决方法的,才得到了这40行算是简短的代码,不知道程序鲁棒性怎么样,欢迎大神指点一二。
分子量 (Molar Mass,ACM/ICPC Seoul 2005,UVa1586)的更多相关文章
- 习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)
#include<stdio.h> #include<string.h> #include<ctype.h> double getweight(char x) { ...
- 分子量(Molar Mass,ACM/ICPC Seoul 2007,UVa 1586)
#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){ char s[20]; scanf ...
- 分子量 (Molar Mass,ACM/ICPC Seoul 2007,UVa 1586)
解题思路: 1.将分子量用double 数组记录下来 2.将字符串存储在字符数组中,从头向后扫描,一直记住“字母”,对下一个字符进行判断,是否是数字,如果是数字:用一个整数记录,本代码中用的sum,同 ...
- UVa 1586 - Molar Mass - ACM/ICPC Seoul 2007 - C语言
关键在于判断数字是两位数还是单位数,其他部分没有难度. #include"stdio.h" #include"string.h" #include"c ...
- [C++]最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583)
Question 例题3-5 最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583) 如果x+x的各个数字之和得到y,就是说x是y的生成元.给出n( ...
- 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)
如果x加上x的各个数字之和得到y,就说x是y的生成元.给出n(1≤n≤100000),求最小 生成元.无解输出0.例如,n=216,121,2005时的解分别为198,0,1979. [分析] 本题看 ...
- 得分(Score,ACM/ICPC Seoul 2005,UVa 1585)
#include<stdio.h> int main(void) { char b; int t,cou,sum; scanf("%d",&t); getcha ...
- 生成元(Digit Generator ,ACM/ICPC Seoul 2005 ,UVa 1583)
生成元:如果 x 加上 x 各个数字之和得到y,则说x是y的生成元. n(1<=n<=100000),求最小生成元,无解输出0. 例如:n=216 , 解是:198 198+1+9+8=2 ...
- 得分(Score, ACM/ICPC Seoul 2005,UVa 1585)
#include<cstdio>#include<cstdlib>#include<cstring>int main(){ char s[80];//输入OOXXO ...
随机推荐
- 网络 私有IP和子网掩码设置
私有IP不需要花钱 节约使用公网IP有两个方法,一个方法是动态IP(关机回收IP),一个方法是私有IP,尤其是私有IP作用巨大. 私有IP不具有唯一性,不能直接访问公网.比如,我以私有IP192.16 ...
- linux 命令格式、ls命令、du命令
命令格式:命令 [-选项] [参数] ls -la /etc1.个别命令不遵循此格式2.当有多个选项时,可以写在一起,大多数顺序可以随意3.简化选项与完整选项 -a 等于 --all ls命令:ls ...
- Storm一个executor里运行多个task是为了rebalance
默认情况下下,一个executor运行一个component,即一个task,但有时会指定多个task: 1 builder.setBolt("", new XxBolt()).s ...
- 带你从零学ReactNative开发跨平台App开发(七)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- 【Java】得到当前股票信息
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; ...
- 的确,Java存在缺陷。但是……
[编者按]本文作者为资深码农 Tim Spann,主要讲述 Java 让人无法抗拒的众多优点以及一些些缺陷.本文系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正文. 早在90年代中期,笔者 ...
- 手动搭建 redis 集群
转自http://meia.fun/article/1544161420745 手动搭建 redis 集群 redis 基本命令: 启动 redis 服务:redis-server xxx.conf ...
- [Asp.net mvc]Asp.net mvc 使用Json传递数据
在之前的练习中一直是直接传递的Model到后台或是单个数据到后台,今天在使用中遇到了点问题,不能使用Model传递到后台,但又要实现多个数据到后台,实验了多次有了以下的解决方案,给自己留个笔记. 功能 ...
- B2B 电商业务之 Quote
商品在网店页面上一般会向买家显示价格.对于B2B, 同一商品对不同的买家可能会展示不同的价格.即使如此,买家仍然可以和卖家再协商价格,最终以不同于网店中显示的价格成交.这个协商价格过程就叫Quote, ...
- phantomJs 快速入门学习 了解大概
1.hellow程序 一个永远的开头,创建一个文件hello.js.内容如下 //hello.js//在窗口输出信息 console.log('Hellow ,Word'); //退出程序,每个脚本必 ...