COP 3223H meeting -*- Outline -*- * Friday Problems with C Structs and Pointer ** vectors ------------------------------------------ VECTORS: ARRAYS WITH LENGTHS Want to combine an array with its size, for: - convenience - bounds checking However, still want to be able to: - pass it efficiently to functions, - access elements in constant time ------------------------------------------ Q: How should we do this? Use a struct with the size in it. To allow parameter passing quickly, allocate the array on the heap, and store a pointer to it in the struct. *** operations ------------------------------------------ WHAT OPERATIONS TO HAVE ON VECTORS? ------------------------------------------ Q: What functions should we build for clients? What kind of operations can we perform on arrays? creation, setting and getting element values we also want to get the size mkvec size vec_get vec_set *** tests For the C type system, we have to settle on an element type, let's use doubles for that... ------------------------------------------ TESTS FOR VECTOR #include "tap.h" #include "vector.h" int main() { plan(5); vector vec5 = mkvec(0.0, 5); ok(vec_size(vec5) == 5, "vec_size(vec5) == 5"); ok(vec_get(vec5, 0) == 0.0, "vec_get(vec5, 0) == 0.0"); ok(vec_get(vec5, 2) == 0.0, "vec_get(vec5, 2) == 0.0"); ok(vec_get(vec5, 4) == 0.0, "vec_get(vec5, 4) == 0.0"); vec_set(vec5, 3, 3.14); ok(vec_get(vec5, 3) == 3.14, "vec_get(vec5, 3) == 3.14"); return exit_status(); } ------------------------------------------ *** data structure ------------------------------------------ WHAT DATA STRUCTURE TO USE? #ifndef VECTOR_H #define VECTOR_H 1 /* ... extern decls for functions ...*/ #endif ------------------------------------------ ... typedef double ELEM; typedef struct vector_s { ELEM *elements; int size; } vector_t; typedef vector_t *vector; *** operations **** creation and initialization ------------------------------------------ CREATION AND INITIALIZATION /* requires: sz > 0 * ensures: result is a vector with the given size, * all of whose elements are initialized to val */ vector mkvec(ELEM val, int sz) { ------------------------------------------ ... vector ret = (vector) malloc(sizeof(vector_t)); ELEM *arr = (ELEM *) malloc(sizeof(ELEM[sz])); ret->elements = arr; // initialize the array for (int i = 0; i < sz; i++) { ret->elements[i] = val; } ret->size = sz; return ret; } **** size ------------------------------------------ // requires: v is allocated (and not NULL) // ensures: result is the size of v; int vec_size(vector v) { } ------------------------------------------ ... return v->size; **** element access and assignment ------------------------------------------ ELEMENT ACCESS AND ASSIGNMENT // requires: v is allocated (and not NULL) // requires: 0 <= i && i < vec_size(v) // ensures: result is the element at index i extern ELEM vec_get(vector v, int i) { // requires: v is allocated (and not NULL) // requires: 0 <= i && i < vec_size(v) // modifies: the element of v at index i // ensures: the element at index i becomes val extern void vec_set(vector v, int i, ELEM val) { ------------------------------------------ ... return v->elements[i]; ... v->elements[i] = val; *** extensions Q: How could we do bounds checking on access and assignment? Q: Could we write a function to do the equivalent of a for loop? Yes, we could pass a function argument to a "map" or "reduce" function... Q: How could we make it so vectors could grow and shrink at runtime? Add operations to do that. Reallocate and copy or use more pointers?