链表中的分段错误(核心转储)错误

时间:2013-10-09 09:51:40

标签: c segmentation-fault

我正在编写一个C程序来表示链表中的多项式。这是我到目前为止所做的。

# include <stdio.h>
# include <stdlib.h>

struct poly
{
    float coef;
    int exp;
    struct poly* next;
};

void make(struct poly**, float, int);
void display(struct poly*);

void add(struct poly*, struct poly*, struct poly**);

int main()
{
    struct poly *first, *second, *final;
    int expa, expb, i;
    float data;

    first = second = final = NULL;

    printf("Enter maximum exponent for polynomial A ");
    scanf("%d", &expa);

    printf("Enter data for polynomial A\n");

    for(i=0;i<=expa;i++)
    {
        printf("Enter coefficient for exponent %d ", expa - i);
        scanf("%f", &data);

        make(&first, data, expa - i);
    }

    printf("Displaying polynomial A ");
    display(first);

    printf("Enter maximum exponent for polynomial B ");
    scanf("%d", &expb);

    printf("Enter data for polynomial B\n");

    for(i=0;i<=expb;i++)
    {
        printf("Enter coefficient for exponent %d ", expb - i);
        scanf("%f", &data);

        make(&second, data, expb - i);
    }

    printf("Displaying polynomial B ");
    display(second);

    printf("Now adding polynomials A and B \n");
    add(first, second, &final);

    display(final);
    return 1;
}

void make(struct poly**head, float coef, int exp)
{
    struct poly *new, *temp;

    new = (struct poly*)malloc(sizeof(struct poly));
    new->coef = coef;
    new->exp = exp;
    new->next = NULL;
    temp = *head;

    if(temp == NULL)
    {
        *head = new;
        return;
    }
    while(temp->next)
        temp = temp->next;

    temp->next = new;
}

void display(struct poly*head)
{
    struct poly*temp = head;

    while(temp)
    {
        printf("%.1fx^%d ", temp->coef, temp->exp);
        temp = temp->next;
    }
    printf("\nExiting display\n");
}

void add(struct poly*first, struct poly*second, struct poly**sum)
{
    struct poly* new;
    printf("Currently in add");
    if(first == NULL && second == NULL)
        return;

    while(first&&second)
    {
        if((*sum)==NULL)
        {
            new = (struct poly*)malloc(sizeof(struct poly));
            *sum = new;
        }
        else
        {
            new->next = (struct poly*)malloc(sizeof(struct poly));
            new = new->next;
        }

        if(first->exp == second->exp)
        {
            new->exp = first->exp;
            new->coef = first->coef + second->coef;

            first = first->next;
            second = second ->next;
        }

        if(first->exp > second->exp)
        {
            new->exp = first->exp;
            new->coef = first->coef;
            first = first->next;
        }

        if(first->exp < second->exp)
        {
            new->exp = second->exp;
            new->coef = second->coef;
            second = second->next;
        }
        new->next = NULL;
    }

    while(first)
    {
        new->next = (struct poly*)malloc(sizeof(struct poly));
        new->coef = first->coef;
        new->exp = first->exp;
        new->next = NULL;
        first = first->next;
    }

    while(second)
    {
        new->next = (struct poly*)malloc(sizeof(struct poly));
        new->coef = second->coef;
        new->exp = second->exp;
        new->next = NULL;
        second= second->next;
    }
}

I am receiving output:
./PolynomialAdditionLinkedList.out 
Enter maximum exponent for polynomial A 2
Enter data for polynomial A
Enter coefficient for exponent 2 1
Enter coefficient for exponent 1 2
Enter coefficient for exponent 0 1
Displaying polynomial A 1.0x^2 2.0x^1 1.0x^0 
Exiting display
Enter maximum exponent for polynomial B 2
Enter data for polynomial B
Enter coefficient for exponent 2 1
Enter coefficient for exponent 1 6
Enter coefficient for exponent 0 9
Displaying polynomial B 1.0x^2 6.0x^1 9.0x^0 
Exiting display
Now adding polynomials A and B 
Segmentation fault (core dumped)

从输出中,看起来我在下面的行中有错误。 add(first, second, &final); As the output doesn't prints目前在添加中,错误发生在它之前。我相信我没有以任何非法的方式修改第一或第二的值? 我在哪里弄错了?

3 个答案:

答案 0 :(得分:3)

add函数中,您有以下代码:

if(first->exp == second->exp)
{
    new->exp = first->exp;
    new->coef = first->coef + second->coef;

    first = first->next;
    second = second ->next;
}

if(first->exp > second->exp)
{
    new->exp = first->exp;
    new->coef = first->coef;
    first = first->next;
}

if(first->exp < second->exp)
{
    new->exp = second->exp;
    new->coef = second->coef;
    second = second->next;
}

现在想想,在第一个if语句中,您处于其中一个列表的最后一个节点时会发生什么。这意味着您将firstsecond设置为NULL。那么其他if语句会发生什么?您将取消引用NULL指针!

您想要的是if-else if链。

答案 1 :(得分:1)

通过删除重复,合并常见情况,可以大大简化add()函数。以下功能使用 goto ,这并不像您想象的那样有害:

struct poly *merge(struct poly *one, struct poly *two)
{
    struct poly *new,*result, **pp;
    fprintf(stderr, "Currently in merge\n");

    result=NULL;
    for(pp= &result; one || two; pp = &(*pp)->next ) {
       *pp = new = malloc (sizeof *new);
       new->next = NULL;
       if (!one) goto use_two;
       if (!two) goto use_one;
          /* when we get here, one and two are both non-null */
       if (one->exp > two->exp) goto use_one;
       if (one->exp < two->exp) goto use_two;
       if (one->exp == two->exp) goto use_both;

use_both: /* useless label for clarity */
       new->coef = one->coef + two->coef;
       new->exp = two->exp;
       two = two->next;
       one = one->next;
       continue;
use_two:
       new->coef = two->coef;
       new->exp = two->exp;
       two = two->next;
       continue;
use_one:
       new->coef = one->coef;
       new->exp = one->exp;
       one = one->next;
       continue;
       }

return result;
}

这应该从main调用:

    ...
    printf("Now adding polynomials A and B \n");
    // add(first, second, &final);
    final = merge (first, second);

    display(final);
    return 0; // <<-- main() should return 0 or EXIT_SUCCESS 
}

一些注意事项:

  • 我更改了函数的签名,它现在返回创建的链接术语列表,而不是将其分配给作为参数传递的指针指针
  • 您可以尝试通过开关,内联函数或宏替换gotos和三个标签。结果将更加混乱,至少不那么紧凑。
  • 特殊情况其中onetwo列表之一已耗尽,现在位于主循环中。没有特殊情况。
  • 将第一个结果节点分配给*head特殊情况正常情况合并(其中*head不为NULL)只需将*pp移动到下一个插入位置即可。再说一遍:没有特殊情况。

答案 2 :(得分:0)

Segmentation fault (core dumped)

由于它已经segfaulted并生成了一个核心文件,你可以启动gdb或你选择的调试器,看看它确切崩溃的位置。

如果您发布,可能有帮助。

正如Alter Mann指出的那样,你使用了新的未初始化的添加:

else
{
    new->next = (struct poly*)malloc(sizeof(struct poly));

如果SUM是非空的,则进入这种情况,并且在第一次迭代时,尚未分配new,因此您将取消引用一些随机指针。哪个不是NULL,因为你没有初始化它,所以即使你确实检查了新的NULL,它仍然可能仍然是段错误。

void add(struct poly*first, struct poly*second, struct poly**sum)
{
    struct poly* new;

应该是:

void add(struct poly*first, struct poly*second, struct poly**sum)
{
    struct poly* new=NULL;

此行不检查新行,它会检查总和。

if((*sum)==NULL)
{
编辑:最后一个想法。你实际上没有检查malloc在任何地方成功。