输入
第一个数字M代表接下来有几组数据;

接下来每一组数据包含两个数据,数字很大哦;
确保没有前缀0,数据很大;

输出
输出计算后的结果,每个结果占一行;

样例输入
3
123 456
1234567890987654321 9876543210123456789
11111111111111111111111111111 111111111111111111111111111111
样例输出
579
11111111101111111110
122222222222222222222222222222
*/

/* 解决这个问题需要处理的小问题:
1.如何存储很长的数字(类型的变量存不了几十位长的整数!)
2.如何将存储的数据以合适的方法取出来,进行计算
/
/
下面用的方法是啰嗦的,但是明确了:往字符数组里填充某个整数,该整数会被视为某个字符的ascii码值.
而往整形数组里填充整数,那促进去的就是整数本省(吗?)
探究了如何从整数存到字符数组,如何从字符数组提取出一位(叫数码吗?)整数(0~9范围的)(相差48/‘0’)
对与0有关的数组的初始化往往会漏带掉导致随机值的莫名其妙
同一数组使用strcpy是十分不建议的. */

#include <stdio.h>
#include <string.h>

// 返回字符串?/指向字符串的指针? char strlonger();
int main(){

//printf("test_4\n");
int n;
while(scanf("%d",&n) != EOF)
{
for(int i = 0;i<n;i++)
{
char recieve_big_number_1[10000];//数组不够大可能无法输出结果/
char recieve_big_number_2[10000];
char sum_up[10000];
scanf("%s%s",recieve_big_number_1,recieve_big_number_2);/* 暂且 将输入大数视为字符串 存入字符数组. */

int dif;/*差值difference */

char *big;
char *small;//char (*small)[100];small = recievi_big_number_1,到底哪种形式可行呢?

int len_small;
int len_big;
int up = 0;
/* 判断那个数大 ,使用abs的话会简洁些*/
if( ( dif = strlen(recieve_big_number_1) - strlen(recieve_big_number_2) ) >= 0)
{
big = recieve_big_number_1;
len_big = strlen(big);
small = recieve_big_number_2;
len_small = strlen(small);
}
else
{
big = recieve_big_number_2;
len_big = strlen(big);
small = recieve_big_number_1;
len_small = strlen(small);
dif = -dif;
}

strcpy(&sum_up[1],big);/* 试图空出sum_up[0]这个可能的最高位. (该操作确实可行) */
/* 当然,这样sum_up[0]的值是随机的,你以选择初始化,当然这题不必须,因为输出的为可能1.从[1]开始输出;2.[0]会被进位值覆盖(为1) */

/* 位置对齐(其实这件事并不必要
,当然,它对于连锁进位还是提供了方便):
但还可以调整填入sum_up的顺序来(高位往后填充,再逆序从高到低输出.)这就无需对齐
事实上,逆(反)序填充,正序输出的手段可以减少很多的不必要的工作量(输出方式是很灵活的),
考试的话前者的定位更合适,平时我们正序排列还正序输出只是为了试验某些知识点,检验思维漏洞(这还未必能办到,就不要死磕)*/
/* 版本一有巨大缺陷 */

// if(dif > 0)
// {
// int j = 0;
// for(int i = 0;i<len_small;i++)
// {
// // 调试时,若看指针的话,只能看到首地址对应元素的变化,更应该观察的是指针所指的源数组的被间接改变的结果
// /*考虑dif== 0, */
// small[i+dif] = small[i];
// //small[i] = '0';这么些的话,前面一串都被赋值为0.考虑另用一个互不干扰的变量
// if(j<dif)
// small[j++] ='0';//'0'就是48啦.(int)

// }
// small[len_small] = '0'; //这句话有待商榷:
// }
/* 版本2 */
//

// strcpy(small[len_big - len_small],small);这里是为什么?处理较长的的输入是就会报错segmentation fault
/* 在同一个字符串中使用strcpy有哪些风险? */
for(int i = 0;i<len_small;i++)
{
/* 如同交换两个变量的值,为了避免重叠的问题,还应开一个buf // 或者考虑从后面的字符开始挪,可以避免重叠造成覆盖,数据丢失*/
/* 值得一提的是,类似的操作再不同的顺序安排下可能产生巨大的不同 */
small[len_small - 1 - i+dif] = small[len_small -1 -i] ;
}
for(int i = 0;i<len_big -len_small;i++)//可以考虑使用字符串函数.
{
small[i] = '0';
}
/* 打个补丁 */
small[len_big] = '\0';
/* 对齐后刷新len_small */
len_small = strlen(small);


/* 将字符转化为数字 */
/* int big_last;
big_last = (int)big[len_big-1] - 48; */
//test将会是存入的数字字符的ASCII值,然而,
//由于ASCII值具有良好的递增规律,-48就可以转换为输入的数字大小了
//printf("%d",test);

/* 小学的按位加法(及进位) */

for(int i = 0;i<len_big /* && i<len_small */;i++)/* i 类似(前移)改变量 */
{ /* 以下可以得到迭代 */

int signal_add_i = 0;
/* signal_add_i本身不依赖于对齐 */

signal_add_i = (int)big[len_big-1 - i ] - 48 + (int)small[len_small-1 -i] - 48 + up ;
up = 0;/* 加完进位,使得进位记录器up归零,否则up回不去了 */
/* 如果发生进位 */
if( signal_add_i >= 10)
{
up = 1;
/* int fill_sum_up;
fill_sum_up = (char)(signal_add_i / 10) + 48;
sum_up[len_big - i ] = fill_sum_up; */
int fill_sum_up;
fill_sum_up = (signal_add_i % 10) + '0';
sum_up[len_big - i ] = fill_sum_up;


}
/* 若不发生进位 */
else
sum_up[len_big - i ] = signal_add_i + '0';

}
//
if(up == 1) /* 我竟然写成了赋值号 = */
{
sum_up[0] = '1';
printf("%s\n",sum_up);
//printf("\n out1 : %s\n",sum_up);//更清楚输出

}

//if(up = 1) sum_up[len_big - len_small - 1] += 1;
/* 打印的时候分个类(首位是否被进位) */
else
printf("%s\n",&sum_up[1]); /* 非首地址,需& */
//printf("\n out2: %s\n",&sum_up[1]);
}

}
return 0;
}

版本_2:(简)

#include <stdio.h>
#include <string.h>
int main()
{
int n;
/* 这块代码不可放在外部(测试多组数据时,有残留)
char s1[100], s2[100];

再开一对整形数组,存储接受的字符串所转化成的整形数据,即提取各位上的数码,便于运算.而且不会破坏输入数据
int num1[31], num2[31], len1, len2, i, j;
*/
while (scanf("%d",&n) != EOF)
{

for (int i = 0; i < n; i++)
{
char s1[10000], s2[10000];/*允许近万位数相加*/

//再开一对整形数组,存储接受的字符串所转化成的整形数据,即提取各位上的数码,便于运算.而且不会破坏输入数据
int num1[10000] = { 0 },/*每一位都初始化为0.*/
num2[10000] = { 0 },
len1, len2, i, j;

scanf("%s%s", s1, s2);/*%s来读取输入*/

len1 = strlen(s1);
len2 = strlen(s2);

/* 两个控制变量,使得字符转数字的填充过程中,低位填在前,高位向后填,方便数位对齐相加*/
i = len1 - 1;/*从最低为起往高位(向前)*/
j = 0;/*从最高位往低位(向后)*/
for (; i >= 0; )
{
num1[j] = s1[i] - 48; //从字符到整数的转换(0~9),并且填充到整形数组
j++;
i--;
}
/*处理第二个操作数*/
for (i = len2 - 1, j = 0; i >= 0; i--)
{

num2[i] = s2[j] - 48;
j++;
}
/* (len2 > len1 ? len2 : len1)的运算结果是len2和len1的较大值,十分紧凑 */
for (i = 0; i < (len2 > len1 ? len2 : len1); i++)
{
/* 将相加(第i位)的结果保存到num1[i]里 */
num1[i] += num2[i];/*相加结果<=9,直接保存(最理想)*/

/* 如果需进位(>9):可以表示位10+k (0<=k<=9) */
if (num1[i] > 9)
{/*向高一位进位+1 */
num1[i + 1] ++; /* 迭代高一位的数码,让其+1 */
/*继续处理当前位:*/
num1[i] -= 10; /* 留下个位,放在当其位置 */
}

} //for(本循环无法判断最高位;两个数相加,若数量级增大,则最高位必为1)

/* 最高位的情况(是否进位,以及填充到适当的位置 还需单独判断下: */

/* 上头的i++在跳出for是已经移位都最高位(如果进位的话) */
/* 最低位放在num1数组的最前面,这样方便处理未知的最高位,届时逆序输出即可
(从后往前打印(高位-->低位)) */

/*如果进位*/
if (num1[i]) /* 最高位是否1(此时的num1[i]只为1/0 (1是低位进上去的;0则是之前memset()初始化的值,且没有进位)) */
{
for (j = i; j >=0 ; j--) /* 或说:j >= 0 */
printf("%d", num1[j]);
printf("\n");
}
/*不进位: */
else
{

for (j = i - 1; j > -1; j--)
printf("%d", num1[j]);
printf("\n");
}

}
}

return 0;
}