华中科技大学 2010 a+b

题目:
        实现一个加法器,使其能够输出a+b的值(a和b的位数不超过1000位)。

思路:
        a和b输入字符串中,并从低到高位以9个字符为一段,对字符串进行分段,然后分别转成整数。a和b对应的整数段相加后,再把结果转成字符串,相连并输出。
        <为什么用9字符为一段?int型最大的数为10位数(2147483647),两个10位数相加可能超过2147483647,导致溢出。 而两个9位数相加则不会溢出,所以采用9字符分段。>

学习与体会:

1.<climits>或<limits.h>头文件,可查看基本数据类型的最大最小值,例:cout<<INT_MAX<<endl。

2.动态分配撤销数组语法:int *intA=new int[dA]; delete [] intA。

3.char* strncpy(char* cc,const char* a,int n);
   作用:把a地址开始的连续n个字符,赋给cc指针所在连续空间。
   头文件:<cstring>或<string.h>
   注意:赋值后,不会自动加'\0'。

   int atoi(const char *str);
   作用:字符串转成整数。
   头文件:<cstdlib>或<stdlib.h>。

   int sprintf (char *a,const char *format,[argument]);
   作用:把格式化的数据写入字符串a中,返回字符串长度。会在末尾自动加'\0'。
   注意:可用它完成int转化成字符串的功能。
//例子:
char cc[20];
int a=11111;
char b='g';
cout<<sprintf(cc,"%d love %c",a,b)<<endl;  
cout<<cc<<endl;    
//输出:
12
11111 love g

   itoa ():int转换成字符串。
   有的平台不支持,被抛弃,所以换用sprintf()函数最好。
4. for(i=0;i<5 && dA!=10;i++):会判断"i<5 && dA!=10"的真假;
    for(i=0;a+=a , dA!=10;i++):会执行"a+=a",并判断"dA!=10"的真假。
5. char*可以和string相加,但结果只能赋给string。也只允许char*赋给string,而不能反过来。<因为string对=和+都有重载>。


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std;

int main(){
	string a,b;                                                                                     //两个相加数
	string Zero[10]={"","0","00","000","0000","00000","000000","0000000","00000000","000000000",};  //整数转回字符串时,填充成9字符串
	int lenA,lenB;                                                                                  //a,b位数
	int dA,dB;                                                                                      //分段段数
	int i,j;
	char cc[10];                                                                                    //字符串段(9个字符)
	
	while(cin>>a>>b){                         //输入两个相加数
		lenA=a.length();                            //求a,b字符串长度
		lenB=b.length();
		if(lenA<=9 && lenB<=9)                      //长度都小于9,则不用分段,直接转整数相加
			cout<<atoi(a.c_str())+atoi(b.c_str())<<endl;
		else{                                       //长度不都小于9,要分段
			dA=lenA/9+(lenA%9?1:0);                       //求a和b分段段数
			dB=lenB/9+(lenB%9?1:0);
			int *intA=new int[dA];                        //申请int数组
			int *intB=new int[dB];
			memset(intA,0,dA*sizeof(int));                //int数组清0
			memset(intB,0,dB*sizeof(int));
			for(i=1;i<dA;i++){                            //把a的分段字符串转成整数,存入intA
				strncpy(cc,&a[lenA-i*9],9);                     //strncpy():某地址开始的几个字符,赋给某字符指针
				cc[9]='\0';
				intA[dA-i]=atoi(cc);                            //atoi():字符串转成int
			}
			strncpy(cc,&a[0],lenA-(dA-1)*9);
			cc[lenA-(dA-1)*9]='\0';
			intA[0]=atoi(cc);

			for(i=1;i<dB;i++){                            //把b的分段字符串转成整数,存入intB
				strncpy(cc,&b[lenB-i*9],9);
				cc[9]='\0';
				intB[dB-i]=atoi(cc);
			}
			strncpy(cc,&b[0],lenB-(dB-1)*9);
			cc[lenB-(dB-1)*9]='\0';
			intB[0]=atoi(cc);
		
			int pub=dA<dB?dA:dB;                          //求公有的段数,和私有段数
			int pri=dA<dB?(dB-pub):(dA-pub);
			int jinwei=0;                                 //进位
			if(dA>dB){                                    //a的段数大于b的段数,则和存入intA[]
				for(i=1;i<=pub;i++){                           //处理共有段
					intA[dA-i]=intB[dB-i]+intA[dA-i]+jinwei;
					if(intA[dA-i]>=1000000000){                      //有进位
						intA[dA-i]-=1000000000;
						jinwei=1;
					}
					else                                             //无进位
						jinwei=0;
				}			
				for(i=pri-1;i>=0 && jinwei!=0;i--){            //处理私有段,一旦进位为0,则不用再处理下去
					intA[i]+=jinwei;
					if(intA[i]>=1000000000){
						intA[i]-=1000000000;
						jinwei=1;
					}
					else
						jinwei=0;
				}
				                                               //把int段转成长度为9的字符串,并重新连接输出
				a=jinwei==1?"1":"";                            //jinwei=1:则要最高位多输出一个1
				memset(cc,'\0',10*sizeof(char));
				sprintf(cc,"%d",intA[0]);                      //sprintf():把数据转成字符串,赋给字符指针
				a+=cc;
				for(i=1;i<dA;i++){
					sprintf(cc,"%d",intA[i]);
					j=strlen(cc);
					a=a+Zero[9-j]+cc;
				}
				cout<<a<<endl;                                 //输出结果
			}
			else{                                         //a的段数不大于b的段数,则和存入intB[]
				for(i=1;i<=pub;i++){                           //处理共有段
					intB[dB-i]=intA[dA-i]+intB[dB-i]+jinwei;
					if(intB[dB-i]>=1000000000){                      //有进位
						intB[dB-i]-=1000000000;
						jinwei=1;
					}
					else                                             //无进位
						jinwei=0;
				}
				for(i=pri-1;i>=0;i--){                         //处理私有段,一旦进位为0,则不用再处理下去
					intB[i]+=jinwei;
					if(intB[i]>=1000000000){
						intB[i]-=1000000000;
						jinwei=1;
					}
					else{
						jinwei=0;
						break;
					}
				}
                                                               //把int段转成长度为9的字符串,并重新连接输出
				b=jinwei==1?"1":"";                            //jinwei=1:则要最高位多输出一个1
				memset(cc,'\0',10*sizeof(char));
				//b+=itoa(intB[0],cc,10);
				sprintf(cc,"%d",intB[0]);
				b+=cc;
				for(i=1;i<dB;i++){
					//itoa(intB[i],cc,10);
					sprintf(cc,"%d",intB[i]);
					j=strlen(cc);
					b=b+Zero[9-j]+cc;
				}
				cout<<b<<endl;                                 //输出结果

			}
			delete [] intA;                               //删除动态申请的intA和intB
			delete [] intB;
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值