COP 3223H meeting -*- Outline -*- * Examples with Structs in C ** rationals Recall the rational numbers that we wrote earlier using arrays. *** data structure Now we can do them better usings structs ------------------------------------------ HEADER FILE FOR RATIONALS // file: rational.h #ifndef RATIONAL_H #define RATIONAL_H 1 #include /* ... extern declarations of all operations */ #endif ------------------------------------------ Q: How should we declare the type ratl to be used in implementing the rationals? ... struct rational { int num; int denom; }; typedef struct rational *ratl; *** coding the operations **** construction and initialization ------------------------------------------ CONSTRUCTION AND INITIALIZATION #include #include "rational.h" /* requires: denom != 0; * ensures: result is a fresh rational number whose * numerator is num and denominator is denom */ ratl rmake(int num, int denom) { ------------------------------------------ Q: How can we return a ratl (== a pointer to a struct rational) without making a dangling pointer? use malloc ... ratl rat = (ratl)malloc(sizeof(struct rational)); rat->num = num; rat->denom = denom; return rat; } **** accessing fields ------------------------------------------ ACCESSING FIELDS ("GETTERS") // ensures: result is the numerator of r int numerator(ratl r) { } // ensures: result is the denominator of r int denominator(ratl r) { } ------------------------------------------ ... return r->num; ... return r->denom; **** transformations ------------------------------------------ TRANSFORMATION OPERATIONS These create new objects from old ones; typical for types with immutable objects. // ensures: result is the sum of x and y ratl radd(ratl x, ratl y) { } // ensures: result is the arithmetic inverse of r ratl rnegate(ratl r) { } // ensures: result is the product of x and y ratl rmult(ratl x, ratl y) { } // requires: the numerator of r is not 0 // ensures: result is the multiplicative inverse of r ratl rinverse(ratl r) { } ------------------------------------------ ... return rmake(numerator(x)*denominator(y) + numerator(y)*denominator(x), denominator(x) * denominator(y)); ... return rmake(- numerator(r), denominator(r)); ... return rmake(numerator(x) * numerator(y), denominator(x) * denominator(y)); ... return rmake(denominator(r), numerator(r)); Q: What's the advantage of writing the code using the getters? We don't have to change it when we change the representation. In fact this code is unchanged from the array version! **** comparisons ------------------------------------------ COMPARISONS // ensures: result is true just when // r1 and r2 are mathematically equal bool requals(ratl r1, ratl r2) { } ------------------------------------------ ... return numerator(r1) * denominator(r2) == denominator(r1) * numerator(r2); Q: How would you implement rleq?