习题3-2 Molar Mass Uva1586
两种思路:
- 一个是循环,当前数组元素如果为字母,判断之后有多少数字,一次性计算,如果循环再碰到数字就跳过。
- 另一个是循环过程中,判断当前取到的是数字还是字母,如果是字母,则记下它的原子质量,继续取下一个。如果是数字,就把记录的上个原子质量*当前的数字。
▲.捣鼓了很久才注意到的是分离数组中数字时,不是用int(s[i])而是s[i]-'0'
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define maxn 105
char s[maxn];
int main()
{
int T;
scanf("%d",&T); //T个输入数据
while(T--)
{
int i;
double single=1.0,sum=0.0;
scanf("%s",s);
int len = strlen(s);
for(i=0;i<len;i++)
{
if (isalpha(s[i]))
{
if(s[i]=='C') single=12.01f;
else if(s[i]=='H') single=1.008f;
else if(s[i]=='O') single=16.00f;
else if(s[i]=='N') single=14.01f;
//记录当前元素的原子质量
if(s[i+1] != '\0'){
if( isalpha( s[i+1]) ) sum += single*1.0;
//如果下一个是字母如OH,就直接加上上个原子的原子质量
else if (isdigit(s[i+1])){ //如果是数字
int j=i+1;
int total=0;
do{
total = 10*total + (s[j]-'0');
j++;
}while(s[j] != '\0' && isdigit(s[j]) );
//把数组内的数字组合成合理的整数。将1、2==>12
sum += single*total;
}
//else sum += single*1.0;
}
else sum += single*1.0; //处理是'\0'情况,C6H5OH的H
}
else continue; //如果是数字就继续循环
}
printf("%.3f\n",sum);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>//system("Pause");调试的时候用的
#define maxn 105
char s[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int i;
double single=1.0,sum=0.0;
scanf("%s",s);
int len = strlen(s);
int flag = 0; //通过该标志判断上一个元素是否是字母
for(i=0;i<len;i++)
{
if (isalpha(s[i]))
{
if(s[i]=='C') {if(flag==1) sum +=single;single=12.01f;flag=1;}
else if(s[i]=='H') {if(flag==1) sum +=single;single=1.008f;flag=1;}
else if(s[i]=='O') {if(flag==1) sum +=single;single=16.00f;flag=1;}
else if(s[i]=='N') {if(flag==1) sum +=single;single=14.01f;flag=1;}
//如果上一个数组元素为字母(flag==1),就直接加上上一个原子质量。
//同时要设置当前数组元素为字母(flag=1)
}
else if (isdigit(s[i]))
{
flag = 0; //设置当前元素为数字
int j=i;
int total=0;
do{total = 10*total + (s[j]-'0');
j++;
}while(s[j] != '\0' && isdigit(s[j]) );
//处理C6H12O6中12这种情况,数字后面没有内容或是字母都结束
sum += single*total;
}
}
if(flag == 1)printf("%.3f\n",sum+single);
//C6H5OH处理最后正好是两个字母的情况,因为判断到最后一个H的时候,sum直接+=了single(0),同时记录了H但没有加上
else printf("%.3f\n", sum);
}
return 0;
}
再奉上mrcrack的做法:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char s[1000+10];
float value(char c){//根据不同的原子,获取相应的原子量
float v;
switch(c){
case 'C':
v=12.01;
break;
case 'H':
v=1.008;
break;
case 'O':
v=16.00;
break;
case 'N':
v=14.01;
break;
}
return v;
}
int main(){
int T;
int len;
int i;
float sum;
int m; //原子的数目
int k;
scanf("%d",&T);
while(T--){
sum=0;
scanf("%s",s);
len=strlen(s);
for(i=0;i<len;i++){
if(isalpha(s[i])){
if(i+1<len){ //元素没越界
if(isdigit(s[i+1])){//下一个元素是数字
k=1;
m=0;
while(i+k<len && isdigit(s[i+k])){
//单个数字连接成一个多位数的数字
m*=10;
m+=s[i+k]-'0';
k++;
}
sum+=value(s[i])*m;
i=i+k-1;//重新开始,i要自加1,故先将i减1
}
else{//下一个元素是字母
m=1;
sum+=value(s[i])*m;
}
}
else{//下一个元素已越界
m=1;
sum+=value(s[i])*m;
}
}
}
printf("%.3f\n",sum);
}
return 0;
}
他的做法跟我的二类似,他在判断是否越界上跟我有略微不同
i+k<len
和s[j+1] != '\0'
.