输入
输入数据有多组。首先输入一个整数T,表示有T组输入。
每组输入两个大整数,并用空格隔开。每个整数最多1000位。没有负数输入。
输出
对于每组输入,输出两个整数的和,单独占一行。
样例输入 Copy
2
1 2
112233445566778899 998877665544332211
样例输出 Copy
3
1111111111111111110
代码一
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,k,n,len1,len2,len;
char a[1000],b[1000];
int sum1[1001],sum2[1001];
scanf("%d",&n);
for(i=0;i<n;i++)
{
//输入两个大整数
scanf("%s%s",&a,&b);
//分别求两个大整数的长度
len1=strlen(a);
len2=strlen(b);
len=len1>len2 ? len1:len2; //len等于最长的那个大整数长度
//分别将sum1[1001],sum2[1001]所有元素初始化为0
memset(sum1,0,sizeof(int)*(len+1));
memset(sum2,0,sizeof(int)*(len+1));
//将两个大整数分别逆序存放入数组sum1与sum2中
for(j=len1-1,k=0;j>=0;j--)
{
sum1[k++]=a[j]-'0';
}
for(j=len2-1,k=0;j>=0;j--)
{
sum2[k++]=b[j]-'0';
}
//进行相加操作
for(j=0;j<len;j++)
{
sum1[j]+=sum2[j];
//判断是否需要进位
if(sum1[j]>=10)
{
sum1[j+1]++;
sum1[j]-=10; //进位后要减10
}
}
//判断是否进位,若进位了,则输出
if(sum1[len]>0)
printf("%d",sum1[len]);
//将剩下的相加结果输出
for(j=len-1;j>=0;j--)
printf("%d",sum1[j]);
printf("\n");
}
return 0;
}
代码一说明
(1)大整数相加有一个需要处理的便是进位问题,因此将两个大整数以字符串形式存入字符串数组后,计算其长度len1,len2,再让len等于其中较大的一个
(2)将两个整数数组sum1,sum2的前len+1个元素利用memset函数全部赋值为0(为了方便处理进位),再将两个大整数分别逆序存入sum1,sum2中,这样若存在进位则可以向后进位
(3)记得在逆序存入时每个字符都要减去字符’0’,因为读入大整数时以字符串形式读入,每个数字都是字符型数字,对其进行运算是对其 ASCII码进行运算,只有减去字符’0’再存入整数数组后才能进行正常的按照其数字含义进行运算
(4)最后便可以利用循环从0到len-1对sum1和sum2进行相加并将结果存入sum1数组中,其中每次相加后都要判断相加后的结果是否大于等于10,若是,则说明需要进位,便让sum1的下一个元素加1,并且让相加后的结果减去10。
(5)因此如果最后一位相加存在进位时,便可以让sum1中的sum1[len]这个元素接收进位后的结果
(6)在输出时,首先通过sum1[len]的值判断是否进位,若进位了则将sum1[len]输出,然后在逆序输出接下来的sum1中的元素。
代码二
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000],b[1000]; //定义两个字符数组,存储大整数
int sum1[1000],sum2[1000],sum[1000],len1,len2,i,n,t=0;
scanf("%d",&n);
while(n--)
{
//对数组进行初始化赋值为0操作
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
memset(sum,0,sizeof(sum));
//输入
scanf("%s",a);
scanf("%s",b);
//求两个大整数的长度
len1=strlen(a);
len2=strlen(b);
//对大整数进行位数补齐操作
if(len1>len2)
{
t=len1-len2; //t为两个大整数的长度差
//若a[1000]=12345,b[1000]=45,补齐后,sum1[1000]=12345,sum2[1000]=00045
for(i=0;i<len1;i++)
{
sum1[i]=a[i]-'0'; //将第一个大整数转为整数型存入数组sum1
if(i<len2)
sum2[i+t]=b[i]-'0';
}
}
else
{
t=len2-len1;
for(i=0;i<len2;i++)
{
sum2[i]=b[i]-'0';
if(i<len1)
sum1[i+t]=a[i]-'0';
}
}
//让len1等于两个大整数长度的最大值
if(len1<len2)
{
t=len1;len1=len2;len2=t;
}
t=0;
for(i=len1-1;i>=0;i--)
{
sum[i]=sum1[i]+sum2[i]+t; //从末位开始相加
t=0; //进位标志位
//判断是否需要进位
if(i>0)
{
if(sum[i]>=10)
{
sum[i]=sum[i]%10;
t=1;
}
}
}
//输出结果
for(i=0;i<len1;i++)
printf("%d",sum[i]);
printf("\n");
}
return 0;
}
代码二说明
(1)这个代码在输入两个大整数后,将其进行减’0’处理后存入整数型数组sum1[1000]和sum2[1000]中方便进行相加操作,并对其进行位数补齐,比如若a[1000]=12345,b[1000]=45,补齐后,sum1[1000]=12345,sum2[1000]=00045 ,
(2)然后将这个两个数组进行逆序相加,也就是从末位也就是从低位开始相加,在相加时还要加上一个t,然后将相加值存入整数型数组sum[1000]中,t用来接收上一个位的进位,初始时为0,在相加操作完成后也要重新设为0。
(3)在符合进位判断条件sum[i]>=10时,进行如下操作
sum[i]=sum[i]%10
t=1 ,这样在下一位相加时便可以接收上一位的进位
(4)若是两个大整数值相等,比如a[1000]=223,b[1000]=921,在进行相加操作时
sum[2]=4
sum[1]=4
sum[0]=11,sum[0]是最高位,不需要进位,这样两个数相加后的值便为1144
大整数相加模板
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000],b[1000]; //定义两个字符数组,存储大整数
int sum1[1000],sum2[1000],sum[1000],len1,len2,i,t=0;
//对数组进行初始化赋值为0操作
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
memset(sum,0,sizeof(sum));
//输入
printf("这是一个大数相加的程序^_^\n");
printf("请输入第一个大数^_^\n");
scanf("%s",a);
printf("请输入第二个大数^_^\n");
scanf("%s",b);
//求两个大整数的长度
len1=strlen(a);
len2=strlen(b);
//对大整数进行位数补齐操作
if(len1>len2)
{
t=len1-len2; //t为两个大整数的长度差
//若a[1000]=12345,b[1000]=45,补齐后,sum1[1000]=12345,sum2[1000]=00045
for(i=0;i<len1;i++)
{
sum1[i]=a[i]-'0'; //将第一个大整数转为整数型存入数组sum1
if(i<len2)
sum2[i+t]=b[i]-'0';
}
}
else
{
t=len2-len1;
for(i=0;i<len2;i++)
{
sum2[i]=b[i]-'0';
if(i<len1)
sum1[i+t]=a[i]-'0';
}
}
//让len1等于两个大整数长度的最大值
if(len1<len2)
{
t=len1;len1=len2;len2=t;
}
t=0;
for(i=len1-1;i>=0;i--)
{
sum[i]=sum1[i]+sum2[i]+t; //从末位开始相加
t=0; //进位标志位
//判断是否需要进位
if(i>0)
{
if(sum[i]>=10)
{
sum[i]=sum[i]%10;
t=1;
}
}
}
//输出结果
for(i=0;i<len1;i++)
printf("%d",sum[i]);
printf("\n");
return 0;
}
memset函数
声明
void *memset(void *str, int c, size_t n)
str – 指向要填充的内存块。
c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
n – 要被设置为该值的字符数。
返回值
该值返回一个指向存储区 str 的指针。
使用
当想对一个数组中的所有元素进行初始化时利用循环一个一个进行操作太过麻烦,利用memset函数可以高效的完成初始化操作。
字符数组例子
#include<stdio.h>
#include<string.h>
int main()
{
int i;
char a[20],b[20],c[20]; //定义三个字符数组,分别初始化为0、1、2
memset(a,'0',sizeof(a)); //发现不以'0'这种形式无输出结果
puts(a);
memset(b,'1',sizeof(char)*10);
puts(b);
memset(c,'f',sizeof(char)*5);
puts(c);
return 0;
}
整数数组例子
#include<stdio.h>
#include<string.h>
int main()
{
int i;
int a[20],b[20];
//初始化 数组a
memset(a,0,sizeof(a));
for(i=0;i<20;i++)
printf("%d ",a[i]);
printf("\n");
//初始化数组b
memset(b,1,sizeof(int)*5);
for(i=0;i<5;i++)
printf("%d ",b[i]);
printf("\n");
return 0;
}
由上可知,对于整数数组若使用memset赋初值并输出赋初值后的数组只有在赋初值为0时直接输出才和赋值的一样,比如上述的20个0,
但要是赋值为1或者其他数的话输出的就是地址,而不是赋的值,很好奇是为什么,但虽然是这样这种赋值也是有效的可以避免因为没有初始化而带来的不必要的问题,也可以用来解决其他问题,比如zzulioj1154校门外的树有一代码便利用了memset将整数数组全部初始化为1然后解决问题
而对于字符型数组只要赋值时为一个字符型的数字或者其他字母就都可以,直接输出初始化后的数组,得到的结果都是自己对数组所赋的值