big_maos 2022-03-30 20:48 采纳率: 100%

# c++使用链表实现大数整数加减，OJ报错Runtime Error:Segmentation fault，请求寻找脏数据

###### 问题相关代码，请勿粘贴截图

``````
#include<iostream>
using namespace std;
int num;
{
num = 0;
prior = NULL;
next = NULL;
}
};

{
if (head == NULL)
{
return;
}

p->num = num;
}

bool exchange(linkedList* a, linkedList* b, int length)
{
for (int i = 1; i <= length; ++i)
{

if (a->num > b->num)
{
return 0;
}
if (a->num < b->num)
{
return 1;
}
if (i != length)
{
a = a->prior;
b = b->prior;
}
}
return 0;
}

{
int extra = 0;
if (type)//加法
{
for (int i = 0; i < len; ++i)
{
c->num += a->num + b->num;
if (c->num > 9)//进位
{
c->num -= 10;
if (c->next != NULL)
{
c->next->num += 1;
}
else //位置不够，延长链表
{
tailC->next = temp;
temp->prior = tailC;
temp->num = 1;
tailC = temp;
extra += 1;
}

}
if (i != len - 1) //最后一次（头一位）计算不要动指针
{
c = c->next;
a = a->next;
b = b->next;
}
}
}
else
{
for (int i = 0; i < len; ++i)
{
c->num += a->num - b->num;
if (c->num < 0)//借位
{
c->num += 10;
c->next->num -= 1;//  自己测试发现出问题地方

}
if (i != len - 1)
{
c = c->next;
a = a->next;
b = b->next;
}
}
}
return extra;
}

{
while (t->prior != NULL)
{
h = t->prior;
delete t;
t = h;
}
delete t;
}

int main()
{
int couunt;
cin >> couunt;
for (int qwe = 0; qwe < couunt; ++qwe)
{
char typeOfCal;
bool type = 1;//加减法
bool minus = 0;//输出的时候需不需要负号
cin >> typeOfCal;
if (typeOfCal == '-')
{
type = !type;
}

char skipA = getchar();//跳过输入里面的回车
linkedList* tailA = NULL;
char singleNumA = getchar();
bool flagA = 0;//大数A符号，0正1负
int cntA = 0;//大数A位数
do
{
if (singleNumA == '-')
{
flagA = !flagA;
singleNumA = getchar();
continue;
}
else if (singleNumA == ',')
{
singleNumA = getchar();
continue;
}
int num = (int)(singleNumA)-48;//字符型的数字->整型
if (headA->next == NULL)//创建尾指针：头指针指向最后一位，尾指针指向头一位（有点奇怪
{
}
singleNumA = getchar();
cntA++;
} while (singleNumA != '\n');

linkedList* tailB = NULL;
char singleNumB = getchar();
bool flagB = 0;
int cntB = 0;
do
{
if (singleNumB == '-')
{
flagB = !flagB;
singleNumB = getchar();
continue;
}
else if (singleNumB == ',')
{
singleNumB = getchar();
continue;
}
int num = (int)(singleNumB)-48;
if (headB->next == NULL)
{
}
singleNumB = getchar();
cntB++;
} while (singleNumB != '\n');

if (!type)//减法的减号放入大数B的符号里面
{
type = 1;
flagB = !flagB;
}
bool flag = 0;
if (flagA && flagB)//两个负号
{
minus = !minus;//提负号
}
else if (!flagA && flagB)//前正后负
{
type = !type;
}
else if (flagA && !flagB)//前负后正
{
type = !type;
minus = !minus;
}
//上述过程把各种符号情况转变为 正+（-）正 ，方便计算
int deltaCnt = cntA - cntB;
if (deltaCnt)//补位，让两个链表长度相等
{
if (deltaCnt < 0)
{
for (int i = 0; i < -deltaCnt; ++i)
{
tailA->next = temp;
temp->prior = tailA;
temp->num = 0;
tailA = temp;
}
}
else
{
for (int i = 0; i < deltaCnt; ++i)
{
tailB->next = temp;
temp->prior = tailB;
temp->num = 0;
tailB = temp;
}
}
}

if (type == 0)//减法中，可能A比B小，此时需要换位置并提负号
{

if (cntA == cntB)
{
flag = exchange(tailA, tailB, cntA);
}
if (cntA < cntB || flag)
{
linkedList* tempT = tailA;
tailA = tailB;
tailB = tempT;
minus = !minus;
}
}

//创建输出的链表，每个节初始化为0
int cntOutput = max(cntA, cntB);
linkedList* tailOutput = NULL;
for (int i = 0; i < cntOutput; ++i)
{
if (headOutput->next == NULL)
{
}
}

//cal函数返回一个值，代表额外进位的个数

int deleteZero = 1;
while (deleteZero)//删除最前面的0（如果有）
{
if (tailOutput->num == 0)
{
linkedList* temp = tailOutput;

tailOutput = tailOutput->prior;
delete temp;
cntOutput--;

}
if (cntOutput == 0)
{
deleteZero = -1;//如果cntOutput一直减到0（结果是0），赋值-1标记
break;
}
if (tailOutput->num != 0)
{
deleteZero = 0;
}

}
//有点乱。。赶时间敲的
linkedList* p = tailOutput;
if (minus && deleteZero != -1)//0不需要输出负号
{
cout << "-";
}
//输出时，从尾指针（头一位）开始
switch (cntOutput % 3) //输出（格式要求）
{
case 0:
{
if (deleteZero != -1)
{
for (int i = 1; i <= cntOutput; ++i)
{
cout << p->num;
if (i % 3 == 0 && i != cntOutput)
{
cout << ",";
}
p = p->prior;
}
cout << endl;

}
else
{
cout << 0 << endl;
}
break;
}
case 1:
{
cout << p->num;
if (cntOutput != 1)
{
cout << ",";
}
p = p->prior;
for (int i = 1; i <= cntOutput - 1; ++i)
{
cout << p->num;
if (i % 3 == 0 && i != cntOutput - 1)
{
cout << ",";
}
p = p->prior;
}
cout << endl;
break;
}
case 2:
{
cout << p->num;
p = p->prior;
cout << p->num;
if (cntOutput != 2)
{
cout << ",";
}
p = p->prior;
for (int i = 1; i <= cntOutput - 2; ++i)
{
cout << p->num;
if (i % 3 == 0 && i != cntOutput - 2)
{
cout << ",";
}
p = p->prior;
}
cout << endl;
break;
}
}

//删除之前创建的链表
if (deleteZero != -1)
{
}
delete p;
}

return 0;
}
``````
###### 运行结果及报错内容

OJ报错Runtime Error:Segmentation fault，百度加上自己的测试，可以确定是产生了野指针（具体位置在代码的备注标注了）

• 写回答

#### 4条回答默认 最新

• 关注

你的逻辑弄的太麻烦了，exchange函数没有必要的，判断一下a和b的大小，在传参的时候，改变一下传参顺序就可以了。
修改后运行结果如下（运行截图中数字之间有空格，代码中已经把空格删掉了）：

代码：

``````
#include<iostream>
using namespace std;
int num;
{
num = 0;
prior = NULL;
next = NULL;
}
};

{
if (head == NULL)
{
return;
}

p->num = num;
}

//加法
{
int flag = 0; //进位
aa = a;
bb = b;
cc = c;
while (aa && bb)
{
p = new linkedList;
p->num = aa->num + bb->num + flag;
if (p->num >= 10)
{
p->num -= 10;
flag = 1;
}
else
flag = 0;

//printf("%d ", p->num);

//插入C
if (cc == NULL)
{
cc = p;
}
else
{
p->next = cc;
cc->prior = p;
cc = p;
}
bb = bb->next;
aa = aa->next;
}

//判断是否有进位
if (flag)
{
p = new linkedList;
p->num = flag;
p->next = cc;
cc->prior = p;
cc = p;
}

c = cc;

return 0;
}
{
int flag = 0; //借位
linkedList* p, * aa, * bb, * cc;
aa = a;
bb = b;
cc = c;
while (aa && bb)
{
p = new linkedList;
p->num = aa->num - bb->num - flag;
if (p->num < 0)
{
p->num += 10;
flag = 1;
}
else
flag = 0;

//插入C
if (cc == NULL)
{
cc = p;
}
else
{
p->next = cc;
cc->prior = p;
cc = p;
}
bb = bb->next;
aa = aa->next;

}
c = cc;
return 0;
}
/*
//逆序显示
{
linkedList* p = tail;
while (p)
{
cout << p->num << " ";
p = p->prior;
}
printf("\n");
}*/

//显示
{
int len=0;
int i=0,k;

while (p)
{
len++;
p = p->next;
}

k = len % 3;
while (p)
{
cout << p->num ;
p = p->next;
i++;
if ((i - k) % 3 == 0)
{
if(p)
cout << ",";
}

}
cout << endl;
}

{
while (t!= NULL)
{
h = t->next;
delete t;
t = h;
}
delete t;
t = 0;
}

//判断a>b
{
linkedList* pa, * pb;
pa = a;
pb = b;
while (pa && pb)
{
if (pa->num > pb->num)
return 1;
else if (pa->num < pb->num)
return -1;
else
{
pa = pa->prior;
pb = pb->prior;
}
}
return 0;
}

int main()
{
int couunt;
cin >> couunt;
for (int qwe = 0; qwe < couunt; ++qwe)
{
char typeOfCal;
bool type = 1;//加减法
bool minus = 0;//输出的时候需不需要负号
cin >> typeOfCal;
if (typeOfCal == '-')
{
type = !type;
}

char skipA = getchar();//跳过输入里面的回车
linkedList* tailA = NULL;
char singleNumA = getchar();
bool flagA = 0;//大数A符号，0正1负
int cntA = 0;//大数A位数
do
{
if (singleNumA == '-')
{
flagA = !flagA;
singleNumA = getchar();
continue;
}
else if (singleNumA == ',')
{
singleNumA = getchar();
continue;
}
int num = (int)(singleNumA)-48;//字符型的数字->整型
if (headA->next == NULL)//创建尾指针：头指针指向最后一位，尾指针指向头一位（有点奇怪
{
}
singleNumA = getchar();
cntA++;
} while (singleNumA != '\n');

linkedList* tailB = NULL;
char singleNumB = getchar();
bool flagB = 0; //0正1负
int cntB = 0;
do
{
if (singleNumB == '-')
{
flagB = !flagB;
singleNumB = getchar();
continue;
}
else if (singleNumB == ',')
{
singleNumB = getchar();
continue;
}
int num = (int)(singleNumB)-48;
if (headB->next == NULL)
{
}
singleNumB = getchar();
cntB++;
} while (singleNumB != '\n');

//补位，让两个链表长度相等
int deltaCnt = cntA - cntB;
int totalLength = cntA > cntB ? cntA : cntB;
if (deltaCnt)//补位，让两个链表长度相等
{
if (deltaCnt < 0)
{
for (int i = 0; i < -deltaCnt; ++i)
{
tailA->next = temp;
temp->prior = tailA;
temp->num = 0;
tailA = temp;
}
}
else
{
for (int i = 0; i < deltaCnt; ++i)
{
tailB->next = temp;
temp->prior = tailB;
temp->num = 0;
tailB = temp;
}
}
}

//printf("补位后：\n");
//show(tailA);
//show(tailB);

//如果是加法运算
linkedList* tailC = NULL;
if (type) //加法
{
if (flagA == 0 && flagB == 0)//都是正数
{
}
else if (flagA == 0 && flagB == 1) //a正b负
{
int res = isbig(tailA, tailB);
if (res==1)
{
}
else if (res == -1)
{
cout << "-";
}
else
cout << "0" << endl;

}
else if (flagA == 1 && flagB == 0) //a负b正
{
int res = isbig(tailB,tailA);
if (res == 1)
{
}
else if (res == -1)
{
cout << "-";
}
else
cout << "0" << endl;
}
else
{
//结果是负数，输出的时候，前面加-
cout << "-";
}

}
else //减法
{
if (flagA == 0 && flagB == 0)//都是正数
{
int res = isbig(tailA,tailB);
if (res == 1)
{
}
else if (res == -1)
{
cout << "-";
}
else
cout << "0" << endl;
}
else if (flagA == 0 && flagB == 1) //a正b负
{
}
else if (flagA == 1 && flagB == 0) //a负b正
{
cout << "-";
}
else
{
//a负b负
int res = isbig(tailB,tailA);
if (res == 1)
{
}
else if (res == -1)
{
cout << "-";
}
else
cout << "0" << endl;
}
}

//释放内存
}

return 0;
}
``````
本回答被题主选为最佳回答 , 对您是否有帮助呢?
评论 编辑记录

#### 问题事件

• 系统已结题 4月8日
• 已采纳回答 3月31日
• 赞助了问题酬金20元 3月30日
• 创建了问题 3月30日

#### 悬赏问题

• ¥15 python：excel数据写入多个对应word文档
• ¥60 全一数分解素因子和素数循环节位数
• ¥15 ffmpeg如何安装到虚拟环境
• ¥188 寻找能做王者评分提取的