Week 7 Code Examples

// COMP1511 Week 5 Lecture 2
// variables/data are passed into functions by value
// a copy of the value gets passed into the function
// so changes made in the function are on the local copy

#include <stdio.h>

void update(int x, int y);
void swap(int x, int y);

int main(void) {
    int x = 2;
    int y = 5;

    printf("%d %d\n", x, y);
    
    update(x,y);
    printf("%d %d\n", x, y);
    
    swap(x, y);
    printf("%d %d\n", x, y);
    return 0;
}

// This function will only modify the local copy of x and y
void update(int x, int y) {
    x = x + 1;
    y = y - 1;
}

// This function will only modify the local copy of x and y
void swap(int x, int y) {
    int tmp = x;
    x = y;
    y = tmp;
}
// COMP1511 Week 5 Lecture 2
// variables/data are passed into functions by value
// a copy of the value gets passed into the function
// Here we pass in the addresses of the variables
// so we can go directly to their address and modify
// them from within the function

#include <stdio.h>

void update(int *x, int *y);
// TO DO FIX SWAP
void swap(int *x, int *y);

int main(void) {
    int x = 2;
    int y = 5;

    printf("%d %d\n", x, y);
    
    // Pass in the addresses of x and y
    // So update can use the addresses to
    // go modify x and y 
    update(&x, &y);
    printf("%d %d\n", x, y);
    
    //TODO FIX THIS
    swap(&x, &y);
    printf("%d %d\n", x, y);
    return 0;
}

// This function uses pointers.
// We can dereference x and y and modify the data
// at the given addresses
void update(int *x, int *y) {
    *x = *x + 1;
    *y = *y - 1;
}

// This function will only modify the local copy of x and y
// TODO FIX
void swap(int *x, int *y) {
    int tmp = *x;
    *x = *y;
    *y = tmp;
}
// COMP1511 Week 5 Lecture 2
// variables/data are passed into functions by value
// a copy of the value gets passed into the function

#include <stdio.h>

struct point {
    int x;
    int y;
};

void update(struct point p);

int main(void) {
    struct point p;    
    p.x = 10;
    p.y = 9;
    update(p);
	printf("(%d,%d)\n", p.x, p.y);
    return 0;
}

// This function will only modify the local copy of p
void update(struct point p) {
    p.x = p.x + 1;
    p.y = p.y + 1;
}
// COMP1511 Week 5 Lecture 2
// variables/data are passed into functions by value
// a copy of the value gets passed into the function
// TO DO MODIFY THIS TO USE POINTERS

#include <stdio.h>

struct point {
    int x;
    int y;
};

void update(struct point *my_point);
struct point update2(struct point p);

int main(void) {
    struct point p;    
    p.x = 10;
    p.y = 9;

    update(&p);
    printf("(%d,%d)\n", p.x, p.y);
    p = update2(p);
    printf("(%d,%d)\n", p.x, p.y);
    return 0;
}

// This function will only modify the local copy of p
// Modify this version to use pointers.
void update(struct point *my_point) {
    my_point->x = my_point->x + 1;  
    my_point->y = my_point->y + 1;  
}

struct point update2(struct point p) {
    p.x++;
    p.y++;
    return p;
}
// COMP1511 Week 7
// Recap Exercise. 
// Try to read and work out what it will print
// before running the code.

#include <stdio.h>

int main(void) {
    int x = 2;
    int y = 5;

    int *ptr1 = &y;
    int *ptr2 = &x;

    int z = *ptr1 + *ptr2;
    *ptr2 = z * 2;
    printf("%d %d %d %d %d\n", x, y, z, *ptr1, *ptr2);

    ptr1 = ptr2;
    printf("%d %d %d %d %d\n", x, y, z, *ptr1, *ptr2);

    return 0;
}
// COMP1511 Week 7
// A demonstration to show how arrays are stored in memory

#include <stdio.h>
#define MAX_LEN 5

void print_array(int *nums, int length);
void print_array2(int nums[], int length);

int main(void) {
    int array[MAX_LEN] = {9, 2, 3};

    printf("array address: %p\n", array);

    int i = 0;
    while (i < MAX_LEN) {
         printf("Address of array[%d] = %p\n", i, &array[i]);
         i++;
    }

    print_array(array, MAX_LEN);
    print_array2(array, MAX_LEN);
    
    return 0;
}

void print_array(int *nums, int length) {
    printf("\naddress of array in print_array: %p\n", nums);
    for (int i = 0; i < length; i++) {
        printf("%d\n", nums[i]);
    }
}

void print_array2(int nums[], int length) {
    printf("\naddress of array in print_array: %p\n", nums);
    for (int i = 0; i < length; i++) {
        printf("%d\n", nums[i]);
    }
}
// COMP1511 Week 7

#include <stdio.h>

#define MAX_LEN 5

void print_array(int nums[], int length);
void increment_all(int nums[], int length);

int main(void) {
    int nums[MAX_LEN] = {1, 2, 3, 4, 5};
    
    printf("Before increment all: \n");
    print_array(nums, MAX_LEN);

    increment_all(nums, MAX_LEN);

    printf("After increment all: \n");
    print_array(nums, MAX_LEN);
    return 0;
}

void print_array(int nums[], int length) {
    int i = 0;
    while (i < length) {
        printf("%d ", nums[i]);
        i++;
    }
    printf("\n");
}

void increment_all(int nums[], int length) { 
    for (int i = 0; i < length; i++) {
        nums[i] = nums[i] + 1;
    }
}
// COMP1511 Week 7
#include <stdio.h>

int main(void) {
    char s[] = "Pointers!!!";
     
    char *sp = &s[1];
    printf("%c\n", *sp);
    printf("%c\n", sp[0]);
    printf("%c\n", sp[1]);
    printf("%s\n", sp);
    
    sp = &s[8];
    printf("%s\n", sp);

    //We can't move where s points.
    //s = &s[1];

    return 0;
}
// Week 7 Lecture 1
// An example of returning an address of a local variable.
// Do NOT do this

#include <stdio.h>
#include <stdlib.h>

#define MAX 5

int *create_array(void);
void print_array(int nums[], int size);

int main(void) {
    int *data = create_array();
    print_array(data, MAX);
    return 0;
}

// returns a pointer to a malloced array
int *create_array(void) {
    int data[MAX];
    for (int i = 0; i < MAX; i++) {
        data[i] = i*10;
    }
    return data;
}

void print_array(int nums[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d\n", nums[i]);
    }
}
// Week 7 Lecture 1
// An example of returning an address of a local variable.
// Do NOT do this

#include <stdio.h>
#include <stdlib.h>

#define MAX 5

int *create_array(void);
void print_array(int nums[], int size);

int main(void) {
    int *data = create_array();
    print_array(data, MAX);
    free(data);
    return 0;
}

// returns a pointer to a malloced array
int *create_array(void) {
    int *data = malloc(sizeof(int) * MAX);
    if (data == NULL) {
        printf("Out of memory\n");
        exit(1);
    }
    for (int i = 0; i < MAX; i++) {
        data[i] = i*10;
    }
    return data;
}

void print_array(int nums[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d\n", nums[i]);
    }
}
// Week 7 Lecture 1
// An example of creating an array of a size
// determined at run time using malloc

#include <stdio.h>
#include <stdlib.h>

int *create_array(int num_elements);
void print_array(int nums[], int size);

int main(void) {
    int num_elements;
    printf("How many elements? ");
    scanf("%d", &num_elements);
 
    int *data = create_array(num_elements);
    if (data != NULL) {
        print_array(data, num_elements);
        free(data);
    }
    return 0;
}


// returns a pointer to a malloced array
int *create_array(int num_elements) {
    int *data = malloc(num_elements *sizeof(int));
    if (data == NULL) {
        printf("Out of memory\n");
        return NULL;
    }
    // You can still use array notation!!!!
    for (int i = 0; i < num_elements; i++) {
        data[i] = i*10;
    }
    return data;
}

void print_array(int nums[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d\n", nums[i]);
    }
}
// Week 7 Lecture 2
// An example of creating and returning a malloced struct
// from a function

#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 128

struct coordinate {
    int x;
    int y;
};

// Write a function to return a pointer 
// to a coordinate struct with given x and y
struct coordinate *create_coordinate(int x, int y);

// prints out the coordinate in the format (x, y)
void print_coordinate(struct coordinate *p);

int main(void) {
    // Call the first function to create a coordinate with 
    // with coordinates (10, -1) 
    struct coordinate *my_coord = create_coordinate(10, -1);
    // Call the second function to print the coordinate
    print_coordinate(my_coord);
    

    struct coordinate *my_coord2 = create_coordinate(9, 1000);
    // Call the second function to print the coordinate
    print_coordinate(my_coord2);
    // Anything else we need to do?

    free(my_coord);
    free(my_coord2);
    return 0;
}

// Write a function to return a pointer 
// to a coordinate struct with given x and y
struct coordinate *create_coordinate(int x, int y) { 
    struct coordinate *new_coord = malloc(sizeof(struct coordinate));
    if (new_coord == NULL) {
        printf("Out of memory\n");
        exit(1);
    }
    new_coord->x = x;
    new_coord->y = y;
    return new_coord;
}

// prints out the coordinate in the format (x, y)
void print_coordinate(struct coordinate *p) {
    printf("(%d, %d)\n", p->x, p->y);
}
// Week 7 Lecture 2
// An example of creating and returning a malloced struct
// from a function

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 128


struct person {
    char name[MAX_LEN];
    int age;
};

// return a pointer to a person struct with name and age
struct person *create_person(char *name, int age);
void print_person(struct person the_person);
 

int main(void) {
    struct person *my_person = create_person("Tina Arena", 58);
    print_person(*my_person);
    free(my_person);
    return 0;
}


// return a pointer to a person struct with name and age
struct person *create_person(char *name, int age) {
    struct person *new_person = malloc(sizeof(struct person));
    if (new_person == NULL) {
        return NULL;
    }
    strcpy(new_person->name, name);
    new_person->age = age;
    return new_person;
}

void print_person(struct person the_person) {
    printf("%s %d\n", the_person.name, the_person.age);
}
// Week 7 Lecture 1
// An example of creating a memory leak 
// on purpose

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int i = 0;
      
    while(1) {
        printf("%d\n", i);
        int *data = malloc(1000000 *sizeof(int));
        if (data == NULL) {
            printf("Out of memory\n");
            return 0;
        }
        i++;
        free(data);
    }
    
    return 0;
}
#include <stdio.h>

int *f(void);

int main(void) {
    int *p = f();
    if (p != NULL) {
        printf("%d\n", *p);
    }
    return 0;
}

int *f(void) {
    return NULL;
}
// An example of creating an array of a size
// determined at run time using malloc
// then resized using realloc
// This is more of an advanced example

#include <stdio.h>
#include <stdlib.h>

int *create_array(int num_elements);
void print_array(int nums[], int size);


int main(void) {
    int num_elements;
    printf("How many elements? ");
    scanf("%d", &num_elements);
 
    int *data = create_array(num_elements);
    if (data == NULL) {
        return 1;
    }

    printf("Original Array: ");
    print_array(data, num_elements);

    // Decide we need a bigger array!
    // Common to double the size if you don't have an exact new size
    // Usually making the array just 1 element larger is not a great idea
    // as you may then ending up reallocing many times. But this is
    // just a simple example
    int new_num_elements = num_elements + 1;

    // In case realloc returns NULL we do not want to lose our 
    // original address of our data
    int *tmp_data = realloc(data, sizeof(int) *new_num_elements);
    if (tmp_data == NULL) {
        //If tmp_data is NULL, we will still have the original array in data
        printf("Can't make it bigger\n");
    } else {
        //If tmp_data was not NULL now that is the address of our new
        //bigger chunk of data
        data = tmp_data;
    }
    // Giving values to the extra data in the array so we can print it 
    // out and see that it is indeed bigger now.
    data[new_num_elements - 1] = 99;

    printf("Realloced Array: ");
    print_array(data, new_num_elements);
   
    //print_array(data, num_elements);
    free(data);
    return 0;
}


// returns a pointer to a malloced array
// or NULL if the malloc failed
int *create_array(int num_elements) {
    int *data = malloc(num_elements *sizeof(int));
    if (data == NULL) {
        printf("Out of memory\n");
        return NULL;
    }
    // You can still use array notation!!!!
    for (int i = 0; i < num_elements; i++) {
        data[i] = i*10;
    }
    return data;
}

void print_array(int nums[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", nums[i]);
    }
    printf("\n");
}
// COMP1511 Week 7 Lecture 1
// sizeof can tell us how many bytes our different types or variables
// are stored in
// We need to print it with %lu instead of %d

#include <stdio.h>

struct point{
    int x;
    int y;
    int z;
};


int main(void) {     
    int x = 1;
    printf("Size of x: %lu bytes\n", sizeof x); 
    printf("Size of an int: %lu bytes\n", sizeof(int)); 
    printf("Size of char: %lu bytes\n", sizeof(char));
    printf("Size of double: %lu bytes\n", sizeof(double));
    printf("Size of 10 ints: %lu bytes\n", 10 * sizeof(int));
    printf("Size of struct point: %lu bytes\n", sizeof(struct point));
    printf("Size of a pointer: %lu bytes\n", sizeof(int *));
    return 0;
}
// Week 7 Lecture 1
// Demonstrating multiple file programs
// Note that this .c file has a matching .h file, array_utilities.h
// It #includes this file.
// Note we use "" instead of <> for our own include files.

#include <stdio.h>
#include "array_utilities.h"


// Print every integer in the given array
void print_data(int size, int data[]) {  
    for (int i = 0; i < size; i++) {
        printf("%d ", data[i]);
    }
    printf("\n");
}

// Print every odd integer in the given array
void print_odd_data(int size, int data[]) {
    for (int i = 0; i < size; i++) {
        if(data[i]%2 != 0) {
            printf("%d ", data[i]);
        }
    }
    printf("\n");
}

// Given a size, this function reads in enough integers
// to fill the given array.
// This function does not check for invalid input
void read_data(int size, int data[]) {
    for (int i = 0; i < size; i++) {
        scanf("%d", &data[i]);
    }
}

// returns the maximum in a given array of ints
int find_maximum(int size, int data[]) {
    int max = data[0];  
    for (int i = 1; i < size; i++) {
        if (data[i] > max) {
            max = data[i];
        }
    }
    return max;
}
// This is the header file for our array_utilities module
// The header file can contain: 
// - #defines
// - structs
// - enums
// - function prototypes and any comments

// Print every integer in the given array
void print_data(int size, int data[]);

// Print every odd integer in the given array
void print_odd_data(int size, int data[]);

// Given a size, this function reads in enough integers
// to fill the given array.
// This function does not check for invalid input
void read_data(int size, int data[]);

// returns the maximum in a given array of ints
int find_maximum(int size, int data[]);
// Week 7 Lecture example
// Every program needs exactly one main function
// This is where we drive the program from 
// and where we make calls to our modules. We
// need to inclide the header file for each
// module that we want to use functions from.

#include <stdio.h>

// We need to include our header and use "" not <>
#include "array_utilities.h"

#define MAX_SIZE 3

int main(void) {
    int numbers[MAX_SIZE] = {4, 6, 1};

    if (find_maximum(MAX_SIZE, numbers) == 6) {
        printf("Yay\n");
    } else {
        printf("Uhoh\n");
    }
    return 0;
}
// Week 7 Lecture example
// Every program needs exactly one main function
// This is where we drive the program from 
// and where we make calls to our modules. We
// need to inclide the header file for each
// module that we want to use functions from.

// To compile the whole program:
// dcc -o program program.c array_utilities.c

// To run
// ./program

#include <stdio.h>

// We need to include our header and use "" not <>
#include "array_utilities.h"

#define MAX_SIZE 5

int main(void) {
    int numbers[MAX_SIZE];

    printf("Enter %d ints: ", MAX_SIZE);
    read_data(MAX_SIZE, numbers);
    
    print_data(MAX_SIZE, numbers);

    int max = find_maximum(MAX_SIZE, numbers);    
    printf("The max is %d\n", max);
    return 0;
}
// Week 7 Wednesday Lecture
// Create a list with nodes by adding nodes with data 0..9 to the beginning
// of an empty list
// Use a functions to create nodes
// Use a loop and a function to print nodes
// Test the print function with an empty list
// We will leave the function to free nodes until later
// For now we will have a memory leak in this program

#include <stdio.h>
#include <stdlib.h>

struct node {
    int data;
    struct node *next;
};

struct node *create_node(int data, struct node *next);
void print_list(struct node *head);


int main(void) {
    // Declare and initialise our list
    // Right now this is an empty list but we will add nodes to it
    struct node *head = NULL;


    print_list(head);
    
    // Temporary variable to hold new nodes
    struct node *new_node = NULL; 
    
    //create a node with data value i using function
    //add node to beginning of the list
    for (int i = 0; i < 10; i++) {
        new_node = create_node(i, head);
        head = new_node;
    }

    // Use function to print list
    print_list(head);
    

    // Create an empty list to test print function


    // We will learn how to free our list later
    // For now we have memory leaks
    return 0;
}

struct node *create_node(int data, struct node *next) {
    struct node *new_node = malloc(sizeof(struct node));
    if (new_node == NULL) {
        return NULL;
    }
    new_node->data = data;
    new_node->next = next;
    return new_node;
}

void print_list(struct node *head) {
    struct node *curr = head;
    printf("list:\n");
    while (curr != NULL) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    
    printf("\n");
}
// Week 7 Wednesday Lecture
// Create a list with 3 nodes
// Print the the contents of the first 3 nodes
// Free the nodes at the end
// This is repetitive
// We need to have functions to create nodes
// We need a less manual way to print the list
// We need a less manual way to free nodes


#include <stdio.h>
#include <stdlib.h>

struct node {
    int data;
    struct node *next;
};

int main(void) {
    // Create list 
    struct node *head =  NULL;

    // Print first 3 nodes in list
    struct node *new_node = malloc(sizeof(struct node));
    new_node->data = 9;
    new_node->next = head;

    head = new_node;

    new_node = malloc(sizeof(struct node));
    new_node->data = 2;
    new_node->next = head;
    head = new_node;

    new_node = malloc(sizeof(struct node));
    new_node->data = 7;
    new_node->next = head;
    head = new_node;


    printf("%d ", head->data);
    printf("%d ", head->next->data);
    printf("%d ", head->next->next->data);
    // There were only 3 nodes! This causes an error
    //printf("%d ", head->next->next->next->data);

   
    // Free nodes in list - we will learn this later
    // For now we will leave our memory leaks

    return 0;
}