---
# System prepended metadata

title: Week 2 - Dynamic Arrays

---

# Week 2 - Dynamic Arrays

## Team

>Members:
>
>-Sean Bos [532785]
>-Boxing Jiang [521516]
>
>
> Date:

## Activities
Make sure to have the activities signed off regularly to ensure progress is tracked.

Before you start, download the project from Blackboard and explore the code contained in it.

### Activity 1: Random access

Rewrite the code by replacing **all** expressions in which pointers are dereferenced with equivalent ones that use the *array index operator* ("[..]").

````c
#include <stdio.h>
#define COUNT (50)

void fill_fibonacci(unsigned long long * storage, int count) {
	*storage = 0;
	*(storage + 1) = 1;
	for (int i = 2; i < count; i++) {
		*(storage + i) = *(storage + i - 1) + *(storage + i - 2);
	}
}

int main(void) {
	unsigned long long array[COUNT];
	fill_fibonacci(array, COUNT);
	for (int i = 1; i < COUNT; i++) {
		printf("f(%d) = %llu\n", i, array[i]);
	}
}
````
Rewritten:
```c
#include <stdio.h>
#define COUNT 50

void fill_fibonacci(unsigned long long * storage, int count) {
    storage[0] = 0;
    storage[1] = 1;
    for (int i = 2; i < count; i++) {
        storage[i] = storage[i - 1] + storage[i - 2];
    }
}

int main(void) {
    unsigned long long array[COUNT];
    fill_fibonacci(array, COUNT);
    for (int i = 1; i < COUNT; i++) {
        printf("f(%d) = %llu\n", i, array[i]);
    }
}
```


### Activity 2: Array definition

Explain what each of the three fields of the `array_t` structure listed below is used for.

Find out, for your system, what the maximum number of elements is that can be stored in the array.



```C
typedef struct array {
    size_t capacity;
    size_t count;
    float *data;
} array_t;
```
`Capacity` is the maximun amount of elements the array can hold.
`Count` is the current amount of elements the array is holding.
`Data` is the pointer for us to access the array values.

From my system, the maxinum value of size_t is 18446744073709551615 bytes, which is about 18 quintillion, so the array can hold about 2.25 quintillion elements. 



### Activity 3: Correct initialization

Version 1 is incorrect because it is returning the pointer of a local variable, which can result in undefined behavior. Also, it is not allocating memory on the heap so it is not creating a dynamic array. To fix this, we can use the malloc function to allocate some memory to make a actual dynamic array just like in version 2.

```C
array_t* array_init(array_t *p_array, size_t capacity) { // version 2
    
    if (p_array != NULL) {
        
        p_array->data = malloc(sizeof(float[capacity]));
        p_array->count = 0;
        
        //If p_array->data is not NULL, then capacity is assigned to p_array->capacity, 
        p_array->capacity = p_array->data != NULL ? capacity : 0;
    }
    return p_array;
    
}
```


### Activity 4: Cleaning up

Record your answer here.

Program 1 is correct. On program 2, the variable array didn't allocate any memory unlike program 1, it's freeing the first element of the automatic lifetime variable array which would result in undefined behavaior. 



```c
//program 1 
int main(void) {

     array_t *array = (array_t *) malloc(sizeof(array_t));
     array_init(array, 10);
     // .... do some work ...
     // finally, clean up
     array_destroy(array);
     free(array);
    }


// program 2
int main(void) {
    array_t array;
    array_init(&array, 10);
    // .... do some work ...
    // finally, clean up
    array_destroy(&array);
    free(&array);
}
```

### Activity 5: Resizing an array

Record your function definition here.
The growth rate of dynamic array can be 1.5.

```c

// enlarges the array geometrically so that it can contain at least min_capacity elements

#define ARRAY_GROWTH_RATE 1.5

void array_reserve(array_t *p_array, size_t min_capacity) {

    size_t capacity = p_array->capacity;

    while (capacity < min_capacity) {
        capacity = (capacity + 1) * ARRAY_GROWTH_RATE;
    }

    if (capacity != p_array->capacity) {

        p_array->data = realloc(p_array->data, (sizeof(float) * capacity));


        if (p_array != NULL){ // check if allocation worked

            p_array->capacity = capacity;

        }

        else{

            p_array->capacity = 0;

        }
    }
}
```

### Activity 6: Appending values


```c
void array_append(array_t * arr, float value){

    //check if there's enough space and extend the space if not
    if (arr->capacity == arr->count){
        
        array_reserve(arr, arr->count + 1); //we are just adding one new element

    }

    arr->data[arr->count] = value;
    arr->count++;

}


```


### Activity 7: Inserting values

Record your function definition here.

```c
void array_insert(array_t * arr, size_t index, float value) {
    

    if (index <= arr->capacity) //must be a valid index
    {

        array_append(arr, 0); //since we are inserting, we need extra slot for the old values

        for (size_t i = 0; i < (arr->count - index); i++){

            arr->data[arr->count - i] = arr->data[(arr->count - i) - 1]; //make the 'next' element value to be the 'previous' element value

        }

        arr->data[index] = value;

    }

}


```


### Activity 8: Removing by index

Record your function definition here.

```c
void array_remove(array_t * arr, size_t index) {
    
    for (size_t i = index; i < arr->count - index; i++) {

        arr->data[i] = arr->data[i + 1];

    }

    arr->count--;
}
```

### Activity 9: Constant time complexity

Consant time complexity means the program takes the same time to run no matter what the input size is.

![](https://i.imgur.com/5hDuH1J.png)

### Activity 10: Worst-case time complexity

| Operation       | Worst-case time complexity |
| --------------- | -------------------------- |
| Insert          | Add value to the first index O(n)                         |
| Remove          | Remove the first index value O(n)  |
| Lookup / access | Since it's random access, so O(1)   |


At both the worst-case of `Insert` and `Remove` operations, all elements of the array needs to be shifted, so it's O(n), it scales with the size of the array as it's shifting n amount of elements.

### Activity 11: Complexity of *append*

The average time complexity should be O(1) because you are just inserting a new element. When you don't enouh enough array size and you need to allocate new size, you will just allocate a bigger capacity with realloc and the array doesn't need a new address.



### Activity 12: Storing grades in a dynamically growing array

```c
// keep asking the user to enter a grade, stop when user enters 0
void input_grades(array_t * grades){

    float userInput;
    int studentNumber = 1;

    printf("Enter student %d's grade: \n", studentNumber);
    scanf("%f", &userInput);
    array_append(grades, userInput);

    while (userInput != 0){

        studentNumber++;
        printf("Enter student %d's grade: \n", studentNumber);
        scanf("%f", &userInput);
        array_append(grades, userInput);

    }
}


// computes and returns the average grade
float average(const array_t * grades){

    float gradeSum = 0;

    for (int i = 0; i < (grades->count - 1); i++){

        gradeSum = gradeSum + grades->data[i];


    }

    return (float) gradeSum / (grades->count - 1);

}


// counts and returns the number of grades that are at least the threshold
int num_passed(const array_t * grades, float threshold){

    int numPassedAmount = 0;

    for (int i = 0; i < (grades->count - 1); i++){


        if(grades->data[i] >= threshold){

            numPassedAmount++;
        }

    }

    return numPassedAmount;
}


int main() {

    array_t grades;
    array_init(&grades, 0);
    input_grades(&grades);
    float averageNum = average(&grades);
    int passed = num_passed(&grades, 5.5f);
    printf("Average grade: %.2f\n", averageNum);
    printf("%d out of %zu students passed\n", passed, grades.count - 1);
    array_destroy(&grades);

}
```


## Looking back

### What we've learnt

Formulate at least one lesson learned.

### What were the surprises

Fill in...

### What problems we've encountered

Fill in...

### What was or still is unclear

Fill in...

### How did the group perform?

How was the collaboration? What were the reasons for hick-ups? What worked well? What can be improved next time?





> Written with [StackEdit](https://stackedit.io/).
