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
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
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 data structure array.h o Interface declares operations, not data structure typedef struct Array *Array_T; o Implementation 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
5 6
Example ADT - Client Example ADT - Implementation client.c array.c (1 of 5) #include “array.h” #include “array.h” #include
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 software • 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 implementations, 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 set 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
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
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(“%d “, *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
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