习题 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. Android 进程回收

    1.Android 进程回收策略 众所周知,Android是基于Linux系统的.在Android进程回收策略中,Android进程与Linux进程根据OOM_ADJ阈值进行区分: OOM_ADJ & ...

  2. 用JS实现的常见几种排序算法

    1.快速排序法 function quickSort(a) { if (a.length <= 1) { return a; } var midLength = Math.floor(a.len ...

  3. ES6-let & const

    let和const命令 let 它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. for(let i = 0; i < arr.length; i++){} 用let命 ...

  4. python中的字符串编码问题——3.各操作系统下的不同编码方式

    各操作系统下的不同编码方式  先看一下 linux,python2.7 >>> B = b'\xc3\x84\xc3\xa8' >>> B.decode('utf- ...

  5. 7.Spring MVC静态资源访问

    在SpringMVC中常用的就是Controller与View.但是我们常常会需要访问静态资源,如html,js,css,image等. 默认的访问的URL都会被DispatcherServlet所拦 ...

  6. 干货:如何使用N点虚拟管理系统?

    N点虚拟主机管理系统怎么用呢?最近有许多朋友问我关于这款虚拟主机管理系统如何使用?在讲如何使用N点虚拟主机管理系统之前,我们先来了解一下N点虚拟主机管理系统的介绍. ​      N点虚拟主机管理系统 ...

  7. bat把npm换成淘宝源

    @echo off echo 开始.. npm config set registry http://registry.npm.taobao.org/ && npm install 注 ...

  8. 解决eclipse 文件更新不自动刷新的问题

    打开eclipse 1. Window ===> Preferences ===> General ===> Workspace 2. 勾选 1> Refresh using ...

  9. python---九九乘法表代码

    #_*_ coding:utf-8 _*_# author choco ''' #while循环num1=0while num1<9: num1+=1 num2=1 while num2< ...

  10. [EffectiveC++]item45:运用成员函数模板接受所有兼容类型