CMSC313, Computer Organization & Assembly Language Programming, Fall 2012
Project 6: Polynomials with malloc()
Due: Thursday November 1, 2012, 11:59pm
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

Please actually read these 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

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 offbyone 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 nonzero
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.
Turning in your program
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
Last Modified:
25 Oct 2012 11:33:27 EDT
by
Richard Chang
to Fall 2012 CMSC 313 Homepage