Lab 7 Ex3
You cannot submit for this problem because the homework's deadline is due.
Ex3. Vectors (20 marks)
The C++ standard library offers a very useful data type: std::vector
. A vector is an array with dynamic size. As long as your computer has enough memory, you can store infinitely many elements in a vector without pre-claiming too much memory that you do not actually use.
For this exercise, implement a data type Vector
that models a dynamic array.
We have provided you with a file Vector.h
that contains a struct definition as well as declarations for six functions:
typedef struct {
// Pointer to the beginning of dynamically allocated chunk of memory.
int* data;
// The actual size of the vector.
size_t size;
// The size of the allocated dynamic memory. capacity * sizeof(int) bytes of
// memory is allocated.
size_t capacity;
} Vector;
// Print a vector to stdout. The first line should be the size and capacity of
// the vector, and the second line should be all the elements of the vector. For
// the first line, use "size: %zu, capacity: %zu\n" in printf(). For the second
// line, add one space between adjacent elements. It does not matter whether the
// last element is followed by a space or not. The second line should end with
// '\n'. If size is 0, the second line should only contain '\n'.
void vector_print(const Vector* vec);
// Return an empty vector. Both size and capacity should be zero, and data
// should be NULL.
Vector create_vector(void);
// Destory the vector by freeing the dynamically allocated memory and setting
// size and capacity to 0.
void free_vector(Vector* vec);
// Append element to the end of vec. If vec's capacity is zero, first use
// malloc() to allocate a memory chunk of sizeof(int) and set capacity to 1. If
// vec's size equals capacity (i.e., the vector is full) before element is
// appended and capacity is non-zero, use realloc() to re-allocate the memory
// *such that the new capacity is twice of the old capacity* before appending
// element.
void vector_push_back(Vector* vec, int element);
// Return a const pointer to the element at index (i.e. data[index]). Check for
// out-of-bound access, and if index is out of bound, return NULL.
const int* vector_get(const Vector* vec, size_t index);
// Set data[index] to new_value. Check for out-of-bound access. If index is out
// of bound, return -1; otherwise, return 0.
int vector_set(Vector* vec, size_t index, int new_value);
Implement the three functions in a new file named Vector.c
. Note that to test your function implementation, you need to write your own driver program. Submit Vector.c
only!
Notes:
- Note that
vec
is passed as a pointer toconst
when the function does not modify the vector, and is passed as a normal pointer when the function potentially modifies the vector. This is a good practice and you should follow this when writing your own code. - In C, the
void
inVector create_vector(void);
matters. It states explicitly that the function has absolutely no input argument. This is different from C++ where()
has the same meaning. In C,Vector create_vector();
means the function can take arbitrary number of arguments. gcc and clang behave differently when you pass parameters to functions declared with empty parameter lists. clang emits a warning while gcc does not. Most of the time, this will not cause any issue, but it is a good practice to add thisvoid
to keep your code compatible and consistent with C++. - Always remember to free a dynamically allocated memory block when it is no longer needed! Otherwise you will have memory leaks.
- We choose to return a
const int*
instead ofint
invector_get()
. This is because we want to do out-of-bound checking. If the return type isint
, any return value can be regarded as valid and there exists no return value we can use to denote an error. However, every valid pointer to anint
will not be a null pointer, soNULL
can be used as an error return value if we returnconst int*
s instead. - An
int
does not always take exactly 4 bytes. Its size depends on the computer architecture. This is why we usesizeof(int)
. C indeed has integral types of fixed size defined in <stdint.h>. Use these types when you want well-defined sizes and ranges.
We will use a driver program to test your implementation. An example driver program ex3_sample_test.c
can be downloaded from Canvas, and its output is shown below:
size: 0, capacity: 0
size: 1, capacity: 1
1
size: 2, capacity: 2
1 1
size: 3, capacity: 4
1 1 2
size: 4, capacity: 4
1 1 2 3
size: 5, capacity: 8
1 1 2 3 5
1 2 5
As long as your implementation is correct, you will pass the tests on JOJ. You do not need to worry about I/O except when implementing vector_print()
.
Lab 7 Exercises
- Status
- Finished
- Problems
- 4
- Open Since
- 2022-06-30 18:15
- DDL
- 2022-07-01 23:59
- Extension
- 0.0 hour(s)