C语言习题:考虑要全面(瑕疵)

引言

这周完成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

看到这题我就觉得这题是关于字符串处理的,并且我认为要用指针来做。
该题的亮点在于:
 输入的数字可能有前导0(没有意义的0)
 输入的数字可能是小数
 尾部多余的0

简单思考:

前导0的存在让我们不可能简单地用strcmp函数来比较,第一步我们需要用指针分别找到有意义数字开始的那个地址。当小数点存在时,因为还有可能有后面的’0’存在,所以我们还需要把后面与较长字符串等宽的没有赋值的位置补’0’(不然未赋值的地址里面放着随机值),以及别忘了在最后面的位置补上’\0’来表示字符串结束。如果输入的是一个整数,一个小数,记得补上小数点。
第一位“有意义”的数字
从左到右第一位不为0的数字或者前一位为0且后一位为.的数字
补’0’
可以比较笨的用for语句遍历,也可以用memset函数

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操作,取而代之的是补’.'操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值