今天和女朋友聊算法,无意中看到一个题,世界上所有的物质均可以由元素周期表中的各个元素组合表示,如果给出有一个物质,用程序实现其物质的量的求解,她一听,觉得还比较简单,但是,随着我聊着聊着,发现,好像不是那么容易去解决,因此,决定写一写这个程序。
首先,在分析过程中,我发现有两个比较难得地方,第一个是,元素周期表中表示元素的符号并不是固定长度,有一个字母表示的,也由两个字母表示的,因此,这无疑增加了我们程序的判断难度,第二个,在表示物质的时候,我们不仅有字母的存在,还有数字的存在,而且,数字可以是多位的,也可以是一位的,比如C12O12,CO2等,因此,我们需要通过判断连续数字的长度来确定某一个元素的个数。听到这里,女票觉得好像有了点思路,说,字母一次拿两个,数字也想一次性那多位出来,其实这是不可取的,在程序中,我们最忌讳的就是“变”,啥意思呢,写程序最好的是一段程序可以同时解决多种情况,这和我们平时做事情正好相反,我们平时做文档啥的最喜欢的就是分类,而程序中尽量减少if……else……语句的出现,否则,会觉得程序很乱,而且调错啥的很不容易。
根据问题的描述,首先,我们分析,表示一种元素最多有两个字母,而且如果是两个字母时候,必然是第一位是大写,第二位是小写,这其实告诉我们两个方面的信息,第一、判断一种元素的充要条件是开头是大写字母,因此程序在执行过程中,发现大写字母,就开始判断当前元素是哪一种。循环时,发现本次取出的是小写字母,直接跳过就可以了,因为,它已经跟随其前面的字母做过判断了,第二、就是告诉我们字符数组定义的长度为3以上,因为还有结束字符'\0'. 这也是我们这个问题的第一个关键点,元素判断。
第二个关键点,自然就是元素的个数是多少,事实上,我们在进行数字计算的时候,依然采用的是一位一位拿出来,每次都做成累加运算就ok。这也是一种经典的处理连续数字的方式,不过这里要注意运算时候不能拿ASCII码运算,要注意字符向数字的转化,一般都会注意。
其实我的程序思路很简单, 首先,过来一个字符串,我们利用for循环,将字符串的每一位拿出来,首先要做的是判断,判断是大写字母时,我们对其后面一位进行判断,如果后一位是小写字母,说明这个元素是用两位字母表示,否则就是用一位字母表示,而后,我们再用得到的一位或者两位的结果去查表,找出该元素在表中对应位置的下标,就找到了该元素的摩尔质量。这时候,就将该元素的摩尔质量加在总的物质的摩尔质量对应的变量。之所以这样处理,因为,只要某一种元素的字母出现在字符串中,说明,该元素在该物质中至少出现了一次,所以,先加上一次。
如果该物质中该元素有多个,那么其后肯定要跟大于2的数字,这个数字可能不止一位,因此,当发现某一位是数字字符的时候,就进入一个循环,计算连续数字表示的值是多少,这里也要注意ASCII码和数字的转化,跳出循环的条件是:不是数字字符,然后,将元素的摩尔质量与该数字减一后的结果相乘,然后累加到总的摩尔质量上,为啥是和该数字减一相乘呢,因为,我们前面说,当某个元素的字母出现时,我们就加了一次,如果只有一个该元素,默认是不用写数字的,所以,就不会有这一步操作,他们的结果是正确的,但是,如果是2个的话,就会紧跟着有2的角标,因此,我们需要有上述相乘累加的操作,但是,因为前面已经加过一次了,所以,要先减一,然后相乘相加。
最后面循环结束,输出结果。欢迎大家留言,讨论。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
int i=0,j=0,k=0;
float sum=0;
int count=0;
char element[5], substance[50];
char elements[100][5]={"C","H","O","N","He","Li","Be","B","F","Ne","Na","Mg","Al","Si","P","S","Ci","Ar","K","Ca"};
float index[100]={12.01, 1.008, 16.00, 14.01, 4.003, 6.941, 9.012, 10.81, 19.00, 20.18, 22.99, 24.31, 26.98,28.09,30.97,32.06,35.45,39.95,39.1,40.08};
int num_ele=0;
while(scanf("%s",substance)){
if(!strcmp(substance,"over")){
break;
}
sum=0;
for(i=0;i<strlen(substance);i++){
if(isupper(substance[i])){
if(islower(substance[i+1])){
num_ele = 2;
}
else {
num_ele = 1;
}
if(num_ele){
k=i;
for(j=0;j<num_ele;j++,k++){
element[j] = substance[k];
}
element[j] = 0;
num_ele=0;
j=0;
while(1){
if(!strcmp(element,elements[j])){
break;
}
j++;
}
sum+=index[j];
}
}
else if(isdigit(substance[i])){
count = 0;
while(isdigit(substance[i])){
count = count * 10 + (substance[i] - '0');
i++;
}
i--;
count--;
sum+=(index[j]*count);
}
}
printf("The molar mass of the %s is: %.3f g/mol\n",substance,sum);
}
return 0;
}