ZCMU-4944 字符串处理

下午打了一场ICPC的区域赛,感觉字符串的练习还是不够,晚上找了到细节字符串题目来练练手,特此记录


题目

ZCMU-4944

4944: 字符串处理

Time Limit: 1 Sec Memory Limit: 32 MB
Submit: 153 Solved: 65
[Submit][Status][Web Board]
Description

读入两个字符串,字符串除了数字还可能包括 ‘—’、‘E’、‘e’、’.’,相加之后输出结果,如果是浮点型,要求用科学计数法表示(最多包含10个有效数字)。
Input

输入包含多组测试数据。

每组输入占两行,每行一个字符串,测试数据保证字符串的构成严格按照题目中的描述。

Output

输出两个数字相加的结果,每组输出占一行。
Sample Input

34.56
2.45e2

Sample Output

2.7956e2

思路解释

这道题目涉及到一些字符串的细微操作,首先我们先把读入的字符串进行初始化,把字符串拆解成以下几个部分:小数点前,小数点后,e以及e之后这四个部分,然后分别进行累加计算

这里由于涉及到e后数字和小数点后的抵消关系,我们引入a,来保存预处理过程中能够抵消之后留下的10的幂次

预处理的代码如下:

int flag,c;
long long solve(char *str,int *a)
{
    
    
    flag=0; //记录正负
    c=0; *a=0;
    long long s=0; int b;
    for(int i=0;str[i];i++)
    {
    
    
        if(str[i]=='-') flag=1;
        else if(str[i]=='.') c=1; //存在小数点,c由0->1
        else if(str[i]=='e'||str[i]=='E')
        {
    
    
            sscanf(str+i+1,"%d",&b); //b中存储e后边的数值
            *a+=b; //小数点后的位数和e后边相乘的位数相抵
            break;
        }
        else
        {
    
    
            s=s*10+str[i]-'0'; //e前边的字符一步步转数值
            *a-=c; //记录小数点后的位数
        }
    }
    if(flag) s=-s;
    return s; //返回e前边的数值
}


AC代码

#include<bits/stdc++.h>
using namespace std;
int flag,c;
long long solve(char str[],int *a)
{
    
    
    long long s = 0;
    int b;
    flag = *a = c = 0;
    for(int i=0;str[i];++i){
    
    
        if(str[i]=='.')c = 1;
        else if(str[i]=='e'||str[i]=='E'){
    
    
            sscanf(str+i+1,"%d",&b);
            *a += b;
            break;
        }else if(str[i]=='-')flag = 1;
        else{
    
    
            s = s*10 + str[i]-'0';
            *a -= c;
        }
       
    }
    if(flag)s = -s;
    return s; //返回e前边的数值
}
int main(){
    
    
 char str1[50],str2[50];
       long long s,s1,s2,ans;
       int a1,a2,a,w,flag;
       while(~scanf("%s%s",str1,str2))
       {
    
    
           //预处理两个字符串并得到相应的a
           s1=solve(str1,&a1);
           s2=solve(str2,&a2);
           //把e换算回来并同时扩大相同倍数
           //直到两个相加数的进制位相同
           if(a1<a2)
           {
    
    
               for(;a1<a2;a2--) s2*=10;
           }
           else if(a1>a2)
           {
    
    
               for(;a1>a2;a1--) s1*=10;
           }
           a=a1; s=s1+s2;
           if(!s) //特殊判断和为0直接输出0并跳出循环
           {
    
    
               printf("0\n");
               continue;
           }
           
           while(a<0&&s%10==0)
           {
    
    
               s/=10; a++;
           }
           
           if(a>=0) //非浮点型
           {
    
    
               printf("%lld",s);
               for(int i=0;i<a;i++) printf("0");
               puts(""); continue;
           }
           
           flag=0; //flag记录求和结果的正负
           if(s<0)
           {
    
    
               s=-s; flag=1;
           }
           ans=1;w=0;
           //ans就是浮点数整数部分,w表示小数点移动的位数
           while(ans<=s)
           {
    
    
               ans*=10; w++;
           }
           if(ans>1)
           {
    
    
               ans/=10; w--;
           }
           //负数输出'-'
           if(flag) printf("-"); 
           //输出小数点前边的数值
           printf("%lld",s/ans);
           //输出小数点后边的数值
           if(ans>1) printf(".%lld",s%ans); 
           //输出e后边的数值
           printf("e%d\n",a+w);
       }
    return 0;
    }

总结

这道题有些点挺细的,然后有些地方处理的不好就很麻烦,总之,可以作为一个处理字符串的方法吧,学习一下

猜你喜欢

转载自blog.csdn.net/DAVID3A/article/details/114500613