引言
这周完成OJ题时碰到一个比较有意思的题目,而网上又没有跟该题的题解,所以想跟大家分享一下我的代码和做法。
题目:考虑要全面
Description
给定两个不超过100000位的实数A和B,请你编写程序来判断A与B是否相等。
Input
输入有多组数据。
每组在一行内包含两个实数A和B,A和B可能包含前导0,可能是整数,也可能不是整数。但数据保证A和B均在100000位以内。
Output
对于每组数据,如果相等,那么请在单独的一行中输出“YES”,否则请输出“NO”。
Sample Input
样例输入①
1 2
2 2
3 3
4 3
样例输入②
000000001 1
1.0000000 000001.00000
10.00000 1
010.00001 10.1
1.0 1
1.505 1.5
Sample Output
样例输出①
NO
YES
YES
NO
样例输出②
YES
YES
NO
NO
YES
NO
My opinion
看到这题我就觉得这题是关于字符串处理的,并且我认为要用指针来做。
该题的亮点在于:
1 输入的数字可能有前导0(没有意义的0)
2 输入的数字可能是小数
3 尾部多余的0
简单思考:
前导0的存在让我们不可能简单地用strcmp函数来比较,第一步我们需要用指针分别找到有意义数字开始的那个地址。当小数点存在时,因为还有可能有后面的’0’存在,所以我们还需要把后面与较长字符串等宽的没有赋值的位置补’0’(不然未赋值的地址里面放着随机值),以及别忘了在最后面的位置补上’\0’来表示字符串结束。如果输入的是一个整数,一个小数,记得补上小数点。
第一位“有意义”的数字
从左到右第一位不为0的数字或者前一位为0且后一位为.的数字
补’0’
可以比较笨的用for语句遍历,也可以用memset函数
代码(瑕疵)
#include<stdio.h>
#include<string.h>
/*exi_dec函数来判断是否有小数点*/
int exi_dec(char *p)
{
for(;p<p+strlen(p);p++)
{
if(*p=='.') return 1;
}
return 0;
}
/*loc_dec函数返回小数点离第一位有效数字的距离*/
int loc_dec(char *p)
{
int count=0;
for(;p<p+strlen(p);p++)
{
if(*p=='.') return count;
count++;
}
}
int main(int argc,char *argv[])
{
char a[100000],b[100000];
char *p1=NULL,*p2=NULL;
int len1,len2,maxlen;
while(scanf("%s%s",a,b)!=EOF)
{
p1=a,p2=b;
/*从前往后寻找“有意义的”数字*/
while(1)
{
if(*p1!='0'||(*(p1+1)=='.'&&*p1=='0')) break;
p1++;
}
while(1)
{
if(*p2!='0'||(*(p2+1)=='.'&&*p2=='0')) break;
p2++;
}
len1=strlen(p1),len2=strlen(p2);
maxlen=len1>len2?len1:len2;
/*把后面与较长字符串等宽的没有赋值的位置补'0'*/
if(exi_dec(p1))
{
memset(p1+len1,'0',maxlen-len1);
}
if(exi_dec(p2))
{
memset(p2+len2,'0',maxlen-len2);
}
/*输入一个整数一个小数时补上小数点
if(exi_dec(p1)&&(exi_dec(p2)==0))
{
*(p2+loc_dec(p1))=0;
}
if(exi_dec(p2)&&(exi_dec(p1)==0))
{
*(p1+loc_dec(p2))=0;
}*/
/*在最后面的位置补上'\0'*/
*(p1+maxlen)=0;
*(p2+maxlen)=0;
/*输出*/
if(strcmp(p1,p2)) printf("NO\n");
else printf("YES\n");
}
}
问题
输入一个整数一个小数时无法正确判断,在代码中已注释出。
今天因为笔者有其他事情,这个问题放到下周解决。
深感抱歉!
下面是正确的代码
#include<stdio.h>
#include<string.h>
int Findstart(char *p)
{
int i;
for(i=0;1;i++)
{
if(p[i]!='0') return i;
}
}
int Findend(char *p)
{
int i,j=strlen(p);
for(i=j-1;1;i--)
{
if(p[i]!='0') return i;
}
}
int Finddec(char *p)
{
int i,j=strlen(p);
for(i=0;i<j;i++)
{
if(p[i]=='.') return i;
}
}
int Exidec(char *p)
{
int i,j=strlen(p);
for(i=0;i<j;i++)
{
if(p[i]=='.') return 1;
}
return 0;
}
int main()
{
int startA,startB,endA,endB,decA,decB;
int i,j,flag;
char A[100000],B[100000];
while(scanf("%s %s",A,B)!=EOF)
{
flag=1;
startA=Findstart(A);
startB=Findstart(B);
if(Exidec(A)==0)
{
A[strlen(A)]='.';
}
if(Exidec(B)==0)
{
B[strlen(B)]='.';
}
endA=Findend(A);
endB=Findend(B);
if(endA-startA!=endB-startB)
{
printf("NO\n");
continue;
}
else
{
for(i=startA,j=startB;i<=endA,j<=endB;i++,j++)
{
if(A[i]!=B[j])
{
printf("NO\n");
flag=0;
break;
}
}
if(flag) printf("YES\n");
}
memset(A,'\0',sizeof(A));
memset(B,'\0',sizeof(B));
}
}
由于使用了数组,相对来说比较好理解,它没有补0操作,取而代之的是补’.'操作。