习题 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)的更多相关文章

  1. 习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)

    #include<stdio.h> #include<string.h> #include<ctype.h> double getweight(char x) { ...

  2. 分子量(Molar Mass,ACM/ICPC Seoul 2007,UVa 1586)

    #include<stdio.h>#include<stdlib.h>#include<string.h>int main(){ char s[20]; scanf ...

  3. 分子量 (Molar Mass,ACM/ICPC Seoul 2007,UVa 1586)

    解题思路: 1.将分子量用double 数组记录下来 2.将字符串存储在字符数组中,从头向后扫描,一直记住“字母”,对下一个字符进行判断,是否是数字,如果是数字:用一个整数记录,本代码中用的sum,同 ...

  4. UVa 1586 - Molar Mass - ACM/ICPC Seoul 2007 - C语言

    关键在于判断数字是两位数还是单位数,其他部分没有难度. #include"stdio.h" #include"string.h" #include"c ...

  5. [C++]最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

    Question 例题3-5 最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583) 如果x+x的各个数字之和得到y,就是说x是y的生成元.给出n( ...

  6. 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

    如果x加上x的各个数字之和得到y,就说x是y的生成元.给出n(1≤n≤100000),求最小 生成元.无解输出0.例如,n=216,121,2005时的解分别为198,0,1979. [分析] 本题看 ...

  7. 得分(Score,ACM/ICPC Seoul 2005,UVa 1585)

    #include<stdio.h> int main(void) { char b; int t,cou,sum; scanf("%d",&t); getcha ...

  8. 生成元(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 ...

  9. 得分(Score, ACM/ICPC Seoul 2005,UVa 1585)

    #include<cstdio>#include<cstdlib>#include<cstring>int main(){ char s[80];//输入OOXXO ...

随机推荐

  1. 回归JavaScript基础(一)

    主题:JavaScript简介. 一.JavaScript的起源 JavaScript诞生于1995年.当时,它的主要作用是处理一些输入验证操作.之前的话,都是把表单数据发送到服务器端,然后再去判断有 ...

  2. MVC 实现自定义404错误页

    直接进入正题. 在HomeController中有一个NotFound的Action方法. public ActionResult NotFound() { return View(); } 对应的视 ...

  3. [翻译] ios-image-filters

    ios-image-filters https://github.com/esilverberg/ios-image-filters photoshop-style filter interface ...

  4. SQL脚本运行

    $v=New-Object -ComObject wscript.shell#也可以使用反单引号(`)字符来强制PowerShell将单引号或双引号解释为文本,0不显示命令提示符窗口$v.run(&q ...

  5. 铁乐学python_day23_面向对象进阶1_反射

    铁乐学python_day23_面向对象进阶1_反射 以下内容大部分摘自博客http://www.cnblogs.com/Eva-J/ isinstance()和issubclass() 两者的返回值 ...

  6. shell study

    目录 shell记录 执行脚本 变量使用 注释 shell传递参数 运算符 echo printf test 流程控制 if ... else ... for while until case 跳出循 ...

  7. SpringBoot部署流程

    一.  项目介绍 a)     本项目为SpringBoot项目 b)     使用内置Tomcat容器 一.  操作步骤 a)     配置pom.xml文件,确定打包方式 b)     更改项目返 ...

  8. 人工智能——搜索(1)回溯策略【N皇后问题】

    这学期学<人工智能>(马少平,朱小燕 编著)这本书,里面很多算法听老师讲都听不懂,就想试试写一下看看能不能写出来,就从最简单的回溯策略开始吧. 源码 题目描述 在一个n*n的国际象棋棋盘上 ...

  9. 新锤子驾到,通通闪开—Service Mesh

    微服务方兴未艾如火如荼之际,除 Spring cloud 等经典框架之外,新一代的微服务开发技术正在悄然兴起,那就是Service Mesh(服务网格).2018 年是Service Mesh 元年, ...

  10. 安装ubuntu server时可能会需要的配置

    1.修改源 笔者比较习惯用163的源,配置如下: sudo vi /etc/apt/sources.list 163源为: deb http://mirrors.163.com/ubuntu/ pre ...