题目:
实现一个加法器,使其能够输出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转化成字符串的功能。
作用:把格式化的数据写入字符串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()函数最好。
有的平台不支持,被抛弃,所以换用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"的真假。
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;
}