2019阿里模拟机试以及阿里实习笔试题之字符串实现加减乘除算术(详解+简化,比网上答案更短,思路更清晰)

题目要求:
两个数使用string 表示,请实现一个函数,将他们相加。
注意:
1. 该数可能包含小数,比如:123.07+8796
2. 输入可能有误,请检查是否合法,不合法返回值为false
3. 该数不包含科学计数法。

关键在于提取字符串中的数字信息,然后分辨数字的合法性。比如02+1.2,2.+2,2.3+.2等等不合法情况。主要思路是首先提取符号“.”和“+”的位置,为提取数字做准备,记录符号位置以后,就可以提取一个个单独数字构成一个数。细节中要注意“.”的问题,可能存在一个,且在加号前或者后,可能不存在,可能同时存在两个,一个在加号前,一个在加号后。
附上自己写的代码,仅供参考:

#include<iostream>
#include<cmath>
#include<string> 
using namespace std;

int main()
{
    string a;
    int i,d,k=0,p=0,l1=0,l2=0;   //k为加号位置,l1为第一个小数点位置,l2记录的二个小数点的位置,p记录加符号的数量
    double q,b,c;  //q为第一个数,b为第二个数,c为结果
    cin>>a;
    d=a.length();
    for(i=0;i<=d-1;++i)
    {
        if((a[i]>='0'&&a[i]<='9')||a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'||a[i]=='.')//所选字符符合范围
        {
            if(a[i]=='.')  //小数点
            {
                if(k!=0&&l2==0&&(i-k)!=1)  //判断条件依次为在K之后,l2只有一个,k和l2不相邻
                    l2=i;
                else if(k==0&&l1==0)//同理如上
                    l1=i;
                else {cout<<"false";return 0;}  //否则不满足以上条件,判断小数点位置不合理
            }
            else if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/')//扩展一下,加减乘除
                {k=i;++p;}
        }
        else {cout<<"false";return 0;}
    }
    if(l1==0)//第一个数为整数(无第一个小数点)
    {
        for(i=0;i<k;++i)
            q+=(a[i]-48)*pow(10,k-i-1);}
    else{for(i=0;i<l1;++i)
            q+=(a[i]-48)*pow(10,l1-i-1);//第一个数的整数部分
        for(i=l1+1;i<k;++i)
            q+=(a[i]-48)*pow(10,l1-i);}//第一个数的小数部分
    if(l2==0)//第二个数为整数(无第二个小数点)
    {
        for(i=k+1;i<=d-1;++i)
            b+=(a[i]-48)*pow(10,d-i-1);}
        else{for(i=k+1;i<l2;++i)
                b+=(a[i]-48)*pow(10,l2-i-1);//第二个数的整数部分
            for(i=l2+1;i<=d-1;++i)
                b+=(a[i]-48)*pow(10,l2-i);}//第二个数的小数部分
    if((a[0]=='0'&&l1!=1)||(a[k+1]=='0'&&l2!=k+2)||p!=1||l2==d-1||(l1!=0&&l1==k-1))//这个一个重点,在代码后讨论
            cout<<"false"<<"1";
    else 
    {if(a[k]=='+')
        c=q+b;
    else if(a[k]=='-')
        c=q-b;
        else if(a[k]=='*')
        c=q*b;
        else if(a[k]=='/')
        c=q/b;
    cout<<c;}
   return 0;
}

接着讨论if((a[0]<49||a[0]>57||p!=1||l2==d-1)||(l1!=0&&l1==k-1)),第一个括号里的内容容易理解,判断条件依次为 ①第一个位置为0时排除错误情况(012+1错误,0.12+1正确)②算术符号后边为0时排除错误情况(12+012错误,12+0.12正确)③加号有且仅有一个④第二个小数点不在最后(如2+2.,小数点在最后,不符合要求)⑤其实这个条件是为了排除第一个小数点和加号连在一起的情况(如2.+3,不符合要求),此时有人会说直接用l1==k-1不就行了?这样做会有一个问题,注意l1和K都是由用户决定的,因此有很大的不确定性,采用这种约束条件不符合一个优秀程序员的设计模式。针对于这种情况,如果只有l1==k-1,会发生一种情况:当l1为0,k为1时(即2+2),系统也会判断出错。因此完整条件应该是(l1!=0&&l1==k-1)。

最后,再提供一种有趣的思路,那就是采用正则表达式,利用regex库。
regex r(“(\d+).?(\d+)+-.?(\d+)”);//采用默认的ECMAScript标准
smatch m;
if(regex_match(str,r))
int a=atoi(m[1].str().cstr());//提取第一个捕捉组(\d+)的内容,并保存为int型
……

大家可以评论交流一下。

猜你喜欢

转载自blog.csdn.net/the_king_of_coder/article/details/82459461
今日推荐