## Project 6: Polynomials with malloc()

### Objective

The objective of this programming project is to practice working with pointers and memory allocation.

### Assignment

Your assignment is to modify the polynomials abstract data type (ADT) from Project 5 so that the coefficient array is dynamically allocated using malloc(). Furthermore, in this project, you must pass pointers to the poly structs for function calls.

The new header file (poly6.h) looks like:

#ifndef _POLY6_H #define _POLY6_H typedef struct { unsigned int deg ; // degree of polynomial int *coeff ; // coeff[i] is coefficient of x^i term } poly ; // return pointer to new poly struct with memory allocated // in coeff array for a degree d polynomial poly *new_poly (unsigned int d) ; // return pointer to new poly struct with coefficients initialized poly *init_poly (unsigned int d, const int coeff[]) ; // Add two polynomials. Return pointer to newly allocated poly struct. poly *add_poly ( const poly *p1, const poly *p2) ; // Subtract two polynomials. Return pointer to newly allocated poly // struct. poly *sub_poly ( const poly *p1, const poly *p2) ; // Multiply two polynomials. Return pointer to newly allocated poly // struct. poly *mul_poly ( const poly *p1, const poly *p2) ; // void compact_poly (poly *p) ; // Pretty print void print_poly (const poly *p) ; // free space and set *pp to NULL void del_poly(poly **pp) ; #endif

Notice that the functions add_poly(), sub_poly() and mul_poly() now return pointers. These functions should return pointers to dynamically allocated poly structs which have dynamically allocated coeff arrays. Two poly structs must never share the same coeff array.

There are two new functions in the ADT that help us create new polynomials: new_poly() and init_poly(). A call to new_poly(d) returns a pointer to a newly allocated poly struct that has a newly allocated coeff array for a degree d polynomial (which requires d+1 entries). A call to init_poly(d, coeff) also returns a pointer to a new degree d polynomial, but init() uses the coeff array parameter to initialize the coeff array of the new polynomial. (Don't confuse the two coeff arrays. One is a formal parameter, the other is a field in the poly struct.)

We also have a new function del_poly(pp) that deallocates the dynamically allocated memory used by a polynomial. We are also excessively paranoid and want to zero out the pointer to this space. Hence the parameter pp is a pointer to a pointer to a poly struct. (We are essentially passing a poly pointer by reference.) For example, we might have:

poly *p ; p = new_poly(3) ; // ... do something ... del_poly(&p) ; // p now points to NULL Notice that in the call to del_poly(), the address of p is the actual parameter. This allows del_poly to make p point to NULL. This prevents us from accidentally using the poly struct that has been freed.

The compact_poly() function is extra credit (see below). If you do not want to pursue extra credit then just have compact_poly() return without doing anything:

void compact_poly (poly *p) { return ; }

Once you have implemented these functions, then you can use polynomials in the main function simply by calling functions like this:

int coeff1[] = {2, -1, 1, -2} ; poly *p1 ; p1 = init_poly(3, coeff1) ; int coeff2[] = {1, 3} ; poly *p2 ; p2 = init_poly(1, coeff2) ; poly *answer ; answer = add_poly(p1, p2) ; print_poly(p1) ; printf(" plus ") ; print_poly(p2) ; printf(" equals ") ; print_poly(answer) ; printf("\n") ; del_poly(&answer) ; The code above should produce output that looks like: -2 x^3 + x^2 - x + 2 plus 3 x + 1 equals -2 x^3 + x^2 + 2 x + 3

### Implementation Notes

• You must work with the header file poly6.h given in /afs/umbc.edu/users/c/h/chang/pub/cs313/poly6.h You are not allowed to alter this file.

• Please call your implementation file poly6.c. This is not required by the C programming language, but makes it much easier for the graders to compile 80 programming assignments.

• Your poly6.c file must be compilable separately. The grader will use a separate test program with its own main() function. Make sure that your functions can be compiled with another program using: linux1% gcc -c poly6.c linux1% gcc -c test6.c linux1% gcc test6.o poly6.o In particular, do not put a main function in poly6.c and do not have #include "poly6.c" in your main program. (You should be including poly6.h not poly6.c.)

• In order to use malloc() and free() you must #include <stdlib.h>

• Do use the sizeof() operator to determine the sizeof of your data for malloc().

• Do not use the C99 feature that allows you to create local variable arrays with sizes determined at run time. (If you don't know what this feature is, great.)

• There are many opportunities for off-by-one errors because:
• A polynomial with degree d actually has d + 1 terms.
• An array with d + 1 entries is indexed from 0 thru d, inclusive.

• We are no longer using the constant MAX_DEG. Before adding, subtracting or multiplying two polynomials, you should allocate a large enough array for the coeff field.

• Remember when you free the memory for a poly struct, you have to free the coeff array first.

• You have to allow for the possibility that your polynomial is the zero polynomial. (This is the polynomial that is just the constant 0.) Make sure that your print_poly() function can print the zero polynomial.

• A small test file is available at: /afs/umbc.edu/users/c/h/chang/pub/cs313/main6.c This has the same test cases as in Project 5, just updated with the new syntax for this project. You should make your own test cases and submit them.

### Extra Credit

For 10% extra credit, implement the compact_poly(p) function. This function reduces the size of the coefficient array in p to just the right size. This function is needed because it is possible to add or subtract two polynomials and have the leading term cancel out. The resulting polynomial can have lower degree than the two original polynomials.

The compact_poly(p) function should find the non-zero term with highest degree stored in *p. If this degree is lower than indicated in p->deg then the function should allocate a new (smaller) coefficient array, copy over the coefficients and free the old coefficient array. The compact_poly() function must also update the deg field. Finally, compact_poly() should handle the special case of the zero polynomial, which should be stored as a degree 0 polynomial with a single coefficient that is 0. (Do not use a NULL pointer to represent the zero polynomial.)

When you have implemented the compact_poly() function, use it in your add_poly(), sub_poly() and mul_poly() functions. For full credit, you must include test cases that demonstrate that your compact_poly() implementation works.

Use the UNIX submit command on the GL system to turn in your project.

When you are done, use the script Unix command to record yourself running your program.

You should submit 3 files: main6.c, poly6.c and typescript. You should not submit poly6.h since this must be identical to the one distributed. Note: main6.c must have test cases that demonstrate the features of your program. You should not rely on the simple test cases in the original main6.c.

The UNIX command to submit should look like:

submit cs313 proj6 main6.c poly6.c typescript