任意长度正数的相减

  • 问题描述:    

两个任意长度的正数相减,这两个正数可以带小数点,也可以是整数,请输出结果。 输入的字符串中,不会出现除了数字与小数点以外的其它字符,不会出现多个小数点以及小数点在第一个字符的位置等非法情况,所以考生的程序中无须考虑输入的数值字符串非法的情况。 
详细要求以及约束:
1.输入均为正数,但输出可能为负数; 
2.输入输出均为字符串形式;
3.如果输出是正数则不需要带符号,如果为负数,则输出的结果字符串需要带负号
例如:2.2-1.1 直接输出为“1.1”,1.1-2.2 则需要输出为“-1.1”
 4.输出的结果字符串需要过滤掉整数位前以及小数位后无效的0,小数位为全0的,直接输出整数位
例如相减结果为11.345,此数值前后均不可以带0,“011.345”或者“0011.34500”等等前后带无效0的均视为错误 输出。例如1.1-1.1结果为0.0,则直接输出0

  • 要求实现函数:
Description  : 两个任意长度的正数相减
Prototype    : int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
Input Param  : const char *pMinuend     被减数,以\0表示字符串结束
               const char *pSubtrahend  减数,以\0表示字符串结束
Output       : char **ppResult          减法结果,必须以\0表示字符串结束
Return Value : 成功返回0   失败返回-1


代码如下:
#include <stdlib.h>
#include <string>






//得到小数点的位置
int getDot(const char *pMinuend)//小数点计算函数
{
int i=0;
while(*(pMinuend+i) != '.' && i< strlen(pMinuend))
{

i++;
}
return i;
}


/*****************************************************************************
Description  : 两个任意长度的正数相减
Prototype    : int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
Input Param  : const char *pMinuend     被减数,以\0表示字符串结束
               const char *pSubtrahend  减数,以\0表示字符串结束
Output       : char **ppResult          减法结果,必须以\0表示字符串结束
Return Value : 成功返回0   失败返回-1
*****************************************************************************/
int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
{


    /* 在这里实现功能 */
if(pMinuend == NULL || pSubtrahend == NULL || pMinuend[0] == '\0' || pSubtrahend[0] == '\0')
{

return -1;
}
else
    {

    //1.得到pMinuend和pSubtrahend的小数点位置
int dot1 = getDot(pMinuend),dot2 = getDot(pSubtrahend);
//2.得到pMinuend和pSubtrahend的长度
int len1 = strlen(pMinuend),len2 = strlen(pSubtrahend);
//3.得到pMinuend的整数部分长度和小数部分长度
    int pMinuend_big=dot1,pMinuend_small=len1-dot1-1;
if(pMinuend_small < 0) pMinuend_small=0;
//4.得到pSubtrahend的整数部分长度和小数部分长度
    int pSubtrahend_big=dot2,pSubtrahend_small=len2-dot2-1;
if(pSubtrahend_small < 0) pSubtrahend_small=0;
//5.得到统一格式后的小数点位置
int dot3=dot1 > dot2 ? dot1:dot2;
//6.得到统一格式后的小数部分长度
int small_len=pMinuend_small > pSubtrahend_small ? pMinuend_small:pSubtrahend_small;
//7.得到统一格式后的字符串长度
int len3;
if(small_len == 0)
{
 //无小数部分
      len3=dot3;
}
else 
{
 len3=dot3+small_len+1;
}
//8.定义三个统一格式后的字符串,分别存储减数,被减数,和结果,并初始化为0
char* str1 = (char *)malloc(len3+1);//加1为了存结束符
char* str2 = (char *)malloc(len3+1);
char* result = (char *)malloc(len3+1);


memset(str1,'0',len3);
memset(str2,'0',len3);
memset(result,'0',len3);


str1[len3] = '\0';
str2[len3] = '\0';
result[len3] = '\0';

//9.将数据存入到统一格式后的字符串中
int i,j;
//先存被减数的
j=dot3-1;
for(i=dot1-1;i>=0;i--)
{

str1[j]=pMinuend[i];
j--;
}
j=dot3+1;
for(i=dot1+1;i<len1;i++)
{

str1[j]=pMinuend[i];
j++;
}
if(str1[dot3] != '\0')
{

        str1[dot3]='.';
}
//再存减数
    j=dot3-1;
for(i=dot2-1;i>=0;i--)
{

str2[j]=pSubtrahend[i];
j--;
}
j=dot3+1;
for(i=dot2+1;i<len2;i++)
{

str2[j]=pSubtrahend[i];
j++;
}
if(str2[dot3] != '\0')
{

        str2[dot3]='.';
}


//10.定义两个指针,分别指向最大,最小值,定义一个标志,判断被减数是否小于减数
char *max,*min;
int flag=0;//默认不小于
if(strcmp(str1,str2) >= 0)
{

max=str1;
min=str2;
}
else
{

max=str2;
min=str1;
flag=1;
}


//11.定义一个函数,大数减去小数,结果保存在,result中,从右往左进行计算,并考虑进位问题
//i标记最后一位,j为进位,temp为结果缓存
int temp;
for(i=len3-1;i>=0;i--)
{

if(max[i] == '.')
{

result[i]='.';
}
else if(max[i]-min[i] >= 0)
{

temp=max[i]-min[i];
result[i]=temp+'0';
}
else//考虑进位
{

temp=10+max[i]-min[i];
//标记到可以提供进位的下标
j=i-1;
while(max[j] < '1')
{

j--;
}
//进位之后,max[j]-1;
max[j]=max[j]-1;
//往后修改各个位数,直到i-1
j=j+1;
while(j != i)
{

if(max[j]=='.')
{

j++;
}
else
{

max[j]='9';
j++;
}
}
             result[i]=temp+'0';
}


//      result[i]=temp+'0';


}


//12.将result中的字符去掉首位和末尾的0
//去掉首位的0
i=0;
int length=len3;
while(result[i] == '0')
{

i++;
length--;
}
//去掉末尾的0
j=len3-1;
while(result[j] == '0')
{

j--;
length--;
}
//如果第一个是小数点,加上0,即后退一个下标
if(result[i] == '.')
{

i--;
length++;
}
//如果最后一个是小数点,删掉
if(result[j] == '.')
{

j--;
length--;
}
    //13.把i到j的范围赋值给p,并考虑正负数
    char*p=(char*)malloc(length*sizeof(char)+2);
if(flag == 1)
{
  //分配多一个空间,从1开始赋值
  int m=1;
  for(int k=i;k<=j;k++)
  {

 p[m]=result[k];
 m++;
  }
  p[0]='-';
  p[m]='\0';


}
else
{
  int m=0;
  for(int k=i;k<=j;k++)
  {

 p[m]=result[k];
 m++;
  }
  p[m]='\0';
}




   //13.将result赋值给*ppResult
*ppResult=p;
//14.释放内存
free(str1);
free(str2);
free(result);
return 0;
}




}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值