Structures stringarray.h #define MAX_STRINGS 128

struct StringArray { char *strings[MAX_STRINGS]; int nstrings; }; Abstract Data Types extern void ReadStrings(struct StringArray *stringarray, FILE *fp); extern void WriteStrings(struct StringArray *stringarray, FILE *fp); extern void SortStrings(struct StringArray *stringarray); sort.c #include CS 217 #include “stringarray.h” int main() { struct StringArray *stringarray = malloc( sizeof(struct StringArray) ); stringarray->nstrings = 0;

ReadStrings(stringarray, stdin); SortStrings(stringarray); WriteStrings(stringarray, stdout);

free(stringarray); return 0; 1 } 2

Typedef Opaque Pointers stringarray.h stringarray.h #define MAX_STRINGS 128 typedef struct StringArray *StringArray_T; typedef struct StringArray { char *strings[MAX_STRINGS]; extern StringArray_T NewStrings(void); int nstrings; extern void FreeStrings(StringArray_T stringarray); } *StringArray_T; extern void ReadStrings(StringArray_T stringarray, FILE *fp); extern void ReadStrings(StringArray_T stringarray, FILE *fp); extern void WriteStrings(StringArray_T stringarray, FILE *fp); extern void WriteStrings(StringArray_T stringarray, FILE *fp); extern void SortStrings(StringArray_T stringarray); extern void SortStrings(StringArray_T stringarray); sort.c sort.c #include #include #include “stringarray.h” #include “stringarray.h”

int main() int main() { { StringArray_T stringarray = malloc( sizeof(struct StringArray) ); StringArray_T stringarray = NewStrings(); stringarray->nstrings = 0; ReadStrings(stringarray, stdin); ReadStrings(stringarray, stdin); SortStrings(stringarray); SortStrings(stringarray); WriteStrings(stringarray, stdout); WriteStrings(stringarray, stdout); FreeStrings(stringarray); free(stringarray); return 0; return 0; } 3 } 4 Abstract Data Types Array ADT - Interface

• Module supporting operations on single array.h o Interface declares operations, not data structure typedef struct Array *Array_T; o is hidden from client (encapsulation) o Use features of programming language to ensure encapsulation extern Array_T Array_new(void); extern void Array_free(Array_T array);

• Common practice extern int Array_getLength(Array_T array); Allocation and deallocation of data structure handled by module extern char *Array_getData(Array_T array, int index); o extern int Array_getIndex(Array_T array, char *str); o Names of functions and variables begin with _ Provide as much generality/flexibility in interface as possible extern void Array_append(Array_T array, char *str); o extern void Array_insert(Array_T array, int index, char *str); o Use void pointers to allow polymorphism extern void Array_replace(Array_T array, int index, char *str); extern void Array_remove(Array_T array, int index); extern void Array_sort(Array_T array);

5 6

Example ADT - Client Example ADT - Implementation client.c array.c (1 of 5) #include “array.h” #include “array.h” #include #define MAX_ELEMENTS 128 int main() { struct Array { Array_T array; char *elements[MAX_ELEMENTS]; int i; int num_elements; }; array = Array_new();

Array_append(array, “CS217”); Array_T Array_new(void) Array_append(array, “IS”); { Array_append(array, “FUN”); Array_T array = malloc(sizeof(struct Array)); array->num_elements = 0; for (i = 0; i < Array_getLength(array); i++) { return array; char *str = Array_getData(array, i); } printf(str); } void Array_free(Array_T array) Array_free(array); { free(array); return 0; } } 7 8 Example ADT - Implementation Example ADT - Implementation array.c (2 of 5) array.c (3 of 5) int Array_getLength(Array_T array) { void Array_append(Array_T array, char *str) return array->num_elements; { } int index = array->num_elements; array->elements[index] = str; array->num_elements++; void *Array_getData(Array_T array, int index) } { return array->elements[index]; } void Array_replace(Array_T array, int index, char *str) { array->elements[index] = str; int Array_getIndex(Array_T array, char *str) } { int index; for (index = 0; index < array->num_elements; index++) { if (array->elements[index] == str) { return index; break; } } return -1; } 9 10

Example ADT - Implementation Example ADT - Implementation array.c (4 of 5) array.c (5 of 5)

void Array_insert(Array_T array, int index, char *str) void Array_sort(Array_T array) { { int i; int i, j;

for (i = array->num_elements; i > index; i--) for (i = 0; i < array->num_elements; i++) { array->elements[i] = array->elements[i-1]; for (j = i+1; j < array->num_elements; j++) { if (strcmp(array->elements[i], array->elements[j]) > 0) { array->elements[index] = str; char *swap = array->elements[i]; array->num_elements++; array->elements[i] = array->elements[j]; } array->elements[j] = swap; } } void Array_remove(Array_T array, int index) } { } int i;

for (i = index+1; i < array->num_elements; i++) array->elements[i-1] = array->elements[i];

array->num_elements--; } 11 12 Summary Modularity in C

• Modularity is key to good • Use features of programming language o Decompose program into modules to enhance modularity o Provide clear and flexible interfaces o struct typedef • Abstract Data Types o o opaque pointers o Modules supporting operations on data structure o void pointers o Well-designed interfaces hide , but provide flexibility o function pointers • Advantages o Separate compilation o Easier to understand o Easier to test and debug o Easier to reuse code o Easier to make changes

13 14

Abstract Data Types (ADTs) Abstract Data Types (ADTs)

• Module supporting operations on single data structure • Module supporting operations on single data structure o Interface declares operations, not data structure o Interface declares operations, not data structure o Interface provides access to simple, complete of operations o Interface provides access to simple, complete set of operations o Interface provides flexibility and extensibility – Interface provides flexibility and extensibility array.h array.h typedef struct Array *Array_T; typedef struct Array *Array_T;

extern Array_T Array_new(void); extern Array_T Array_new(void); extern void Array_free(Array_T array); extern void Array_free(Array_T array);

extern int Array_getLength(Array_T array); extern int Array_getLength(Array_T array); extern char *Array_getData(Array_T array, int index); extern char *Array_getData(Array_T array, int index); extern int Array_getIndex(Array_T array, char *str); extern int Array_getIndex(Array_T array, char *str);

extern void Array_append(Array_T array, char *str); extern void Array_append(Array_T array, char *str); extern void Array_insert(Array_T array, int index, char *str); extern void Array_insert(Array_T array, int index, char *str); extern void Array_replace(Array_T array, int index, char *str); extern void Array_replace(Array_T array, int index, char *str); extern void Array_remove(Array_T array, int index); extern void Array_remove(Array_T array, int index); extern void Array_sort(Array_T array); extern void Array_sort(Array_T array);

But this array ADT still only holds strings 15 16 Polymorphism - Void Pointers Example ADT - Client 1 string_client.c array.h #include “array.h” #include typedef struct Array *Array_T; int main() extern Array_T Array_new(void); { extern void Array_free(Array_T array); Array_T array; int i; extern int Array_getLength(Array_T array); extern void *Array_getData(Array_T array, int index); array = Array_new(); extern int Array_getIndex(Array_T array, void *datap); Array_append(array, (void *) “CS217”); extern void Array_append(Array_T array, void *datap); Array_append(array, (void *) “IS”); extern void Array_insert(Array_T array, int index, void *datap); Array_append(array, (void *) “FUN”); extern void Array_replace(Array_T array, int index, void *datap); extern void Array_remove(Array_T array, int index); for (i = 0; i < Array_getLength(array); i++) { char *str = (char *) Array_getData(array, i); printf(str); }

Array_free(array);

return 0; } 17 18

Example ADT - Client 2 Pointers

int_client.c • Pointers are variables whose value is an address #include “array.h” #include o They usually point to a variable of a specific type Example: char *str = “CS217”; int main() o { Array_T array; 0x00000000 int one=1, two=2, three=3; int i;

array = Array_new(); 0x10005384 `C` `S` `2` `1` Array_append(array, (void *) &one); `7` `0` Array_append(array, (void *) &two); Array_append(array, (void *) &three);

for (i = 0; i < Array_getLength(array); i++) { 0x10005384 int *datap = (int *) Array_getData(array, i); printf(“% “, *datap); str }

Array_free(array); 0xFFFFFFFF return 0; Memory } 19 20 Void Pointers Void Pointer Implementation

• Void pointers are the same as any other pointer array.c (1 of 4) #include “array.h” o Except they point to a variable with no specific type o Example: void *datap = “CS217”; #define MAX_ELEMENTS 128 struct Array { • Difference: 0x00000000 void *elements[MAX_ELEMENTS]; Compiler does not check int num_elements; o }; type when dereference 0x10005384 `C` `S` `2` `1` • Common Uses: Array_T SAMEArray_new(void) AS BEFORE `7` `0` { o Abstract data types Array_T array = malloc(sizeof(struct Array)); supporting polymorphism array->num_elements = 0; return array; o Pass pointer to function 0x10005384 } EXCEPT ... that could be any of several datap types void Array_free(Array_T array) { 0xFFFFFFFF free(array); } Memory 21 22

Example ADT - Implementation Function Pointers - Interface array.c array.h

void Array_sort(Array_T array) { typedef struct Array *Array_T; int i, j; extern Array_T Array_new(void); for (i = 0; i < array->num_elements; i++) { extern void Array_free(Array_T array); for (j = i+1; j < array->num_elements; j++) { if (strcmp(array->elements[i], array->elements[j]) > 0) { extern int Array_getLength(Array_T array); char *swap = array->elements[i]; extern void *Array_getData(Array_T array, int index); array->elements[i] = array->elements[j]; extern int Array_getIndex(Array_T array, void *datap); array->elements[j] = swap; } extern void Array_append(Array_T array, void *datap); } extern void Array_insert(Array_T array, int index, void *datap); } extern void Array_replace(Array_T array, int index, void *datap); } extern void Array_remove(Array_T array, int index);

extern void Array_sort(Array_T array, int (*compare)(void *datap1, void *datap2)); How do we compare two data elements if we don’t know their types? Pass function pointer to ADT

23 24 Function Pointers - Implementation Function Pointers - Client array.c int_client.c #include “array.h” void Array_sort(Array_T array, #include int (*compare)(void *datap1, void *datap2)) { int CompareInts(void *datap1, void *datap2) int i, j; { int *intp1 = (int *) datap1; for (i = 0; i < array->num_elements; i++) { int *intp2 = (int *) datap2; for (j = i+1; j < array->num_elements; j++) { return (*intp1 - *intp2); if ((*compare)(array->elements[i], array->elements[j]) > 0) { } char *swap = array->elements[i]; Every function name (e.g., CompareInts) array->elements[i] = array->elements[j]; int main() representsrepresents thethe addressaddress ofof aa functionfunction array->elements[j] = swap; { (i.e.,(i.e., aa pointerpointer toto aa function).function). } Array_T array; } int one=1, two=2, three=3; } } array = Array_new(); Array_append(array, (void *) &one); Array_append(array, (void *) &two); Call function by dereferencing function pointer Array_append(array, (void *) &three); Array_sort(array, CompareInts);

etc. } 25 26

Summary

• Module supporting operations on single data structure o Interface declares operations, not data structure o Interface provides access to simple, complete set of operations o Interface provides flexibility and extensibility • Trick is providing functionality AND generality o Take advantage of features of programming language – void pointers – function pointers • Advantages o Provide complete set of commonly used functions (re-use) o Implementation is hidden from client (encapsulation) o Can use for multiple types (polymorphism)

27