-2

I wrote C program to which should add two polynomials. I wrote this program in Kali Linux 2.0 OS. When I execute the program I don't get the required output. Instead I get this-

Polynomial 1

How many no. terms do you want to enter? 1

Enter coefficient for term 1: 2
Enter exponent for term 1: 3

Polynomial 2

How many no. terms do you want to enter? 1

Enter coefficient for term 1: 2
Enter exponent for term 1: 3


Polynomial 1=
Polynomial 2=
Sum of the two polynomials is

The program code is given below-

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

typedef struct node
{
    int exp,coeff;
    struct node *next;
}poly;

poly *headA,*headB,*headC;
poly *lastA,*lastB,*lastC;

void insert(poly*,poly*,poly *);
void input(poly *,poly *);
void display(poly *);

void insert(poly *new,poly *head,poly *last)
{
    poly *p,*q;
    if(head==NULL&&last==NULL)  //setting the start
    {
        head=last=new;
        return;
    }
    p=head;
    q=NULL;
    while(new->exp<p->exp)  
    {
        q=p;
        p=p->next;
    }
    if(p->exp==new->exp)    //if exponents are equal
        p->coeff=p->coeff+new->coeff;
    else
    {
        if(q!=NULL) //insertion in middle
        {
            q->next=new;
            new->next=p;
        }
        else if(q==NULL)    //insertion at beginning
        {
            new->next=head;
            head=new;
        }
        else if(p==NULL)    //insertion at the end
        {
            last->next=new;
            last=new;
        }
    }
}

void input(poly *head,poly *last)
{
    int i,n,c,e;
    poly *new;
    new=(poly *)malloc(sizeof(poly));
    printf("How many no. terms do you want to enter? ");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        printf("\nEnter coefficient for term %d: ",i);
        scanf("%d",&new->coeff);
        printf("Enter exponent for term %d: ",i);
        scanf("%d",&new->exp);
        new->next=NULL;
        insert(new,head,last);
        insert(new,headC,lastC);
    }
}

void display(poly *start)
{
    poly *p;
    p=start;
    while(p!=NULL)
    {
        printf("(%dx^%d)+",p->coeff,p->exp);
        p=p->next;
    }
    printf("\b");
}

void main()
{
    system("clear");

    headA=(poly *)malloc(sizeof(poly));
    headB=(poly *)malloc(sizeof(poly));
    headC=(poly *)malloc(sizeof(poly));
    lastA=(poly *)malloc(sizeof(poly));
    lastB=(poly *)malloc(sizeof(poly));
    lastC=(poly *)malloc(sizeof(poly));

    headA=headB=headC=NULL;
    lastA=lastB=lastC=NULL;

    printf("Polynomial 1\n\n");
    input(headA,lastA);
    printf("\nPolynomial 2\n\n");
    input(headB,lastB);
    printf("\n\nPolynomial 1=");
    display(headA);
    printf("\nPolynomial 2=");
    display(headB);
    printf("\nSum of the two polynomials is=");
    display(headC);
}

Edit: After reading the comments I brought some changes in my code. Now the output is-

Polynomial 1

How many no. terms do you want to enter? 1

Enter coefficient for term 1: 5
Enter exponent for term 1: 6

Polynomial 2

How many no. terms do you want to enter? 2

Enter coefficient for term 1: 6
Enter exponent for term 1: 5

Enter coefficient for term 2: 7
Enter exponent for term 2: 8


Polynomial 1=(0x^0)+
Polynomial 2=(0x^0)+
Sum of the two polynomials is=(0x^0)

The present program code is-

poly *insert(poly*,poly*,poly *);
poly *input(poly *,poly *);
void display(poly *);

poly *insert(poly *new,poly *head,poly *last)
{
    poly *p,*q;
    if(head==NULL&&last==NULL)
    {
        head=last=new;
        return;
    }
    p=head;
    q=NULL;
    while(new->exp<p->exp)
    {
        q=p;
        p=p->next;
    }
    if(p->exp==new->exp)
        p->coeff=p->coeff+new->coeff;
    else
    {
        if(q!=NULL)
        {
            q->next=new;
            new->next=p;
        }
        else if(q==NULL)
        {
            new->next=head;
            head=new;
        }
        else if(p==NULL)
        {
            last->next=new;
            last=new;
        }
    }
    return head;
}

poly *input(poly *head,poly *last)
{
    int i,n,c,e;
    poly *new;
    printf("How many no. terms do you want to enter? ");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        new=(poly *)malloc(sizeof(poly));
        if(new==NULL)
        {
            printf("Allocation Error!!");
            break;
        }
        printf("\nEnter coefficient for term %d: ",i);
        scanf("%d",&new->coeff);
        printf("Enter exponent for term %d: ",i);
        scanf("%d",&new->exp);
        new->next=NULL;
        head=insert(new,head,last);
        headC=insert(new,headC,lastC);
        free(new);
    }
    return head;
}

void display(poly *start)
{
    poly *p;
    p=start;
    while(p!=NULL)
    {
        printf("(%dx^%d)+",p->coeff,p->exp);
        p=p->next;
    }
    printf("\b");
}

void main()
{
    system("clear");

    headA=(poly *)malloc(sizeof(poly));
    headB=(poly *)malloc(sizeof(poly));
    headC=(poly *)malloc(sizeof(poly));
    lastA=(poly *)malloc(sizeof(poly));
    lastB=(poly *)malloc(sizeof(poly));
    lastC=(poly *)malloc(sizeof(poly));

    if(headA==NULL||headB==NULL||headC==NULL||lastA==NULL||lastB==NULL||lastC==NULL)
    {
        printf("Allocation failure!!!");
        return;
    }

    headA=headB=headC=NULL;
    lastA=lastB=lastC=NULL;

    printf("Polynomial 1\n\n");
    headA=input(headA,lastA);
    printf("\nPolynomial 2\n\n");
    headB=input(headB,lastB);
    printf("\n\nPolynomial 1=");
    display(headA);
    printf("\nPolynomial 2=");
    display(headB);
    printf("\nSum of the two polynomials is=");
    display(headC);
}
Dibakar Saha
  • 49
  • 2
  • 9
  • 2
    A starting place would be you are malloc'ing space for headA, headB, headC, lastA, lastB, and lastC in main() ... then immediately assigning NULL to them all... Additionally, every malloc should be followed by a check whether it worked or failed. – TonyB Aug 30 '15 at 22:37
  • 3
    Try stepping through your code line by line. Many things should become apparent. – Raymond Chen Aug 30 '15 at 23:28
  • `head=new;` in `insert()` does not affect `head` in `input()`. Use `&head` and `input(poly **head,poly *last)` (**) – chux - Reinstate Monica Aug 31 '15 at 00:15
  • What do you mean by "stepping thorough your code line by line"? @RaymondChen – Dibakar Saha Aug 31 '15 at 06:02
  • How does that code even compile? Your new `insert` has to return a value of type `poly *`, yet if `head==NULL&&last==NULL`, you just `return`. – pat Aug 31 '15 at 06:14
  • 1
    The type `poly` doesn't really represent a polynomial, it represents a single term of a polynomial. You should rename the type to be `term`, and create a new `poly` type that holds the head and last pointers to a list of `term`s. In this way, `insert` should be passed a pointer to a `poly` and a pointer to a `term`, and should insert the `term` into the `poly`. – pat Aug 31 '15 at 06:16
  • 1
    It also makes no sense to `malloc` 6 `poly`s in main, just to reset all the pointers to `NULL`. You just leaked memory! – pat Aug 31 '15 at 06:17
  • The `input` routine is also trying to insert the same node into both the `head` list and the `headC` list. A node can only live in one list at a time. But then you free the node while it is trying to live in two lists... – pat Aug 31 '15 at 06:32
  • Go through the program line by line with a debugger using the single-step function. Inspect the variables after each step. See if their values agree with what you expect. Clearly there will be a point at which they do not match what you expect, because the program doesn't do what you expect. – Raymond Chen Aug 31 '15 at 14:46

2 Answers2

0

Here's a working version:

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

A term_t describes a single term in a polynomial.

typedef struct term {
    int exp;
    int coeff;
    struct term *next;
} term_t;

A poly_t describes a whole polynomial, which is just a list of terms. The last pointer wasn't really necessary since we always traverse the list from the start.

typedef struct poly {
    term_t *head;
} poly_t;

We need a way to initialize polynomials by setting the list of terms to empty. We also need a way to destroy a polynomial by freeing all of its terms.

void init_poly(poly_t *poly)
{
    poly->head = NULL;
}

void destroy_poly(poly_t *poly)
{
    term_t *term = poly->head;
    while (term != NULL) {
        term_t *nextTerm = term->next;
        free (term);
        term = nextTerm;
    }
    poly->head = NULL;
}

We will also find it necessary to be able to clone a term (create a copy of an existing term). Note that in C, it is not necessary to cast the return value of malloc.

term_t *clone_term(term_t *term)
{
    term_t *new_term;

    if ((new_term = malloc(sizeof *new_term)) == NULL) {
        printf("Allocation failure!!!\n");
        return NULL;
    }

    new_term->coeff = term->coeff;
    new_term->exp = term->exp;
    new_term->next = NULL;
    return new_term;
}

We also need a way to insert a term into a polynomial. Terms are kept sorted by exponent (highest exponent comes earlier in list), but if a term with a matching exponent is already in the polynomial, we simply add to the coefficient. We can eliminate all of the special-case code by maintaining a pointer to the next pointer that we will modify to point to the new term.

void insert_term(poly_t *poly, term_t *term)
{
    term_t **nextPtr = &poly->head;
    term_t *nextTerm;

    while ((nextTerm = *nextPtr) != NULL) {
        if (nextTerm->exp == term->exp) {
            /* we found an existing term with a matching exponent */
            nextTerm->coeff += term->coeff;
            free (term); /* we don't need term so it must be free'd */
            return;
        }
        else if (nextTerm->exp < term->exp) {
            /* the next term has a lower exponent, so we stop here */
            break;
        }
        nextPtr = &nextTerm->next;
    }

    term->next = nextTerm;
    *nextPtr = term;
}

The input_poly function is responsible for inputting only a single polynomial. It allocates a new term_t for each term which it inserts.

int input_poly(poly_t *poly)
{
    int i, n;

    printf("How many terms do you want to enter? ");
    scanf("%d", &n);

    for (i = 0; i < n; i++) {
        term_t *term;

        if ((term = malloc(sizeof *term)) == NULL) {
            printf("Allocation failure!!!\n");
            return -1;
        }

        printf("\nEnter coefficient for term %d: ", i+1);
        scanf("%d", &term->coeff);

        printf("Enter exponent for term %d: ", i+1);
        scanf("%d", &term->exp);

        term->next = NULL;

        insert_term(poly, term);
    }

    return 0;
}

The add_to_poly function adds a polynomial to an existing polynomial. It does this by cloning the terms of the addend, and inserting them into the accumulator. It is necessary to clone each term because a term cannot be a member of two polynomials at the same time. Note that since the exponents of both polynomials are kept in sorted order, this could be done more efficiently.

int add_to_poly(poly_t *accum, const poly_t *addend)
{
    term_t *term;
    for (term = addend->head; term != NULL; term = term->next) {
        term_t *new_term;

        if ((new_term = clone_term(term)) == NULL) {
            return -1;
        }

        insert_term(accum, new_term);
    }

    return 0;
}

Using a backspace character to delete the trailing + may appear to work on a terminal, but it will not work when the output is redirected to a file. It is better to print the separator only when needed.

void display_poly(poly_t *poly)
{
    term_t *term;
    for (term = poly->head; term != NULL; term = term->next) {
        printf("(%dx^%d)", term->coeff, term->exp);
        if (term->next != NULL) {
            printf("+");
        }
    }
}

main is supposed to have the following type signature. We simply initialize our polynomials, input two polynomials, add them and print them.

int main(int argc, char **argv)
{
    poly_t polyA;
    poly_t polyB;
    poly_t polyC;

    init_poly(&polyA);
    init_poly(&polyB);
    init_poly(&polyC);

    printf("Polynomial 1\n\n");
    if (input_poly(&polyA) == -1) {
        goto error;
    }
    printf("\n");

    printf("Polynomial 2\n\n");
    if (input_poly(&polyB) == -1) {
        goto error;
    }
    printf("\n\n");

    if ((add_to_poly(&polyC, &polyA) == -1 ||
         add_to_poly(&polyC, &polyB) == -1)) {
        goto error;
    }

    printf("Polynomial 1=");
    display_poly(&polyA);
    printf("\n");

    printf("\nPolynomial 2=");
    display_poly(&polyB);
    printf("\n");

    printf("\nSum of the two polynomials is=");
    display_poly(&polyC);
    printf("\n");

error:
    destroy_poly(&polyA);
    destroy_poly(&polyB);
    destroy_poly(&polyC);

    return 0;
}
pat
  • 12,587
  • 1
  • 23
  • 52
  • 1
    An answer of "Here's my code", doesn't answer the OP's question "What's wrong with my code?" – David C. Rankin Aug 31 '15 at 13:28
  • Hey @pat I asked what is wrong with my code, not for a working code. But i do appreciate your efforts to help me. I even liked the idea of using two structures poly_t and term_t – Dibakar Saha Aug 31 '15 at 15:17
0

At last.. I found the solution to my problem. I just had to call the head and last pointers by their references. This is solved my problem. Earlier I was using call by value method which did not bring changes to my original values. I even made a few minor changes to my code. Below is my working code-

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

typedef struct node
{
    int exp,coeff;
    struct node *next;
}poly;

poly *headA,*headB,*headC;
poly *lastA,*lastB,*lastC;

void insert(int ,int ,poly **,poly **);
void input(poly **,poly **);
void display(poly *);

void insert(int c,int e,poly **head,poly **last)
{
    poly *p,*q,*new;

    new=(poly *)malloc(sizeof(poly));
    if(new==NULL)
    {
        printf("Allocation error\n");
        return;
    }
    new->coeff=c;
    new->exp=e;
    new->next=NULL;


    if(*head==NULL&&*last==NULL)
    {
        *head=*last=new;
    }
    //insertion at right place
    else
    {
        p=*head;
        q=NULL;
        while(e<p->exp)
        {
            q=p;
            p=p->next;
        }
        if(p->exp==e)
            p->coeff=p->coeff+c;
        else
        {
            if(q!=NULL)
            {
                q->next=new;
                new->next=p;
            }
            else if(q==NULL)
            {
                new->next=*head;
                *head=new;
            }
            else if(p==NULL)
            {
                (*last)->next=new;
                new->next=NULL;
                *last=new;
            }
        }
    }
}

void input(poly **head,poly **last)
{
    int i,n,c,e;
    printf("How many no. terms do you want to enter? ");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        printf("\nEnter coefficient for term %d: ",i);
        scanf("%d",&c);
        printf("Enter exponent for term %d: ",i);
        scanf("%d",&e);
        insert(c,e,head,last);
        insert(c,e,&headC,&lastC);
    }
}

void display(poly *start)
{
    poly *p;
    p=start;
    while(p!=NULL)
    {
        printf("(%dx^%d)+",p->coeff,p->exp);
        p=p->next;
    }
    printf("\b");
    printf(" ");
}

void main()
{
    system("clear");

    headA=(poly *)malloc(sizeof(poly));
    headB=(poly *)malloc(sizeof(poly));
    headC=(poly *)malloc(sizeof(poly));
    lastA=(poly *)malloc(sizeof(poly));
    lastB=(poly *)malloc(sizeof(poly));
    lastC=(poly *)malloc(sizeof(poly));

    if(headA==NULL||headB==NULL||headC==NULL||lastA==NULL||lastB==NULL||lastC==NULL)
    {
        printf("Allocation failure!!!");
        return;
    }

    headA=headB=headC=lastA=lastB=lastC=NULL;

    printf("Polynomial 1\n\n");
    input(&headA,&lastA);
    printf("\nPolynomial 2\n\n");
    input(&headB,&lastB);
    printf("\n\nPolynomial 1=");
    display(headA);
    printf("\nPolynomial 2=");
    display(headB);
    printf("\nSum of the two polynomials is=");
    display(headC);
    printf("\n");
}

Output-

Polynomial 1

How many no. terms do you want to enter? 5

Enter coefficient for term 1: 1
Enter exponent for term 1: 2

Enter coefficient for term 2: 3
Enter exponent for term 2: 4

Enter coefficient for term 3: 5
Enter exponent for term 3: 6

Enter coefficient for term 4: 7
Enter exponent for term 4: 8

Enter coefficient for term 5: 9
Enter exponent for term 5: 10

Polynomial 2

How many no. terms do you want to enter? 5

Enter coefficient for term 1: 1
Enter exponent for term 1: 2

Enter coefficient for term 2: 8
Enter exponent for term 2: 3

Enter coefficient for term 3: 4
Enter exponent for term 3: 2

Enter coefficient for term 4: 0
Enter exponent for term 4: 12

Enter coefficient for term 5: 5
Enter exponent for term 5: 10


Polynomial 1=(9x^10)+(7x^8)+(5x^6)+(3x^4)+(1x^2) 
Polynomial 2=(0x^12)+(5x^10)+(8x^3)+(5x^2) 
Sum of the two polynomials is=(0x^12)+(14x^10)+(7x^8)+(5x^6)+(3x^4)+(8x^3)+(6x^2)
Dibakar Saha
  • 49
  • 2
  • 9