Week 06 Tutorial Questions

Ask students if they have any questions about Assignment

Remind students that week 7 has no tutorials.

Part 1: 2D Arrays Practice (20 mins)

In this section we will write a short program that deals with 2D arrays.

The objective of this program is to simulate the exploration of a galaxy by placing celestial bodies such as stars, planets, and nebulae within a grid.

Functionality

  1. Firstly, the program should prompt for celestial bodies with Enter planets and nebulae: and take input for planets and nebula until q is pressed.

    • Planets are added with p [row] [col] [points]
    • Nebulae are added with n [row] [col]

You may assume you will always be given valid input.

  1. After populating the map with various celestial bodies your program will need to scan in the player's starting position. This will be given as a pair of integers which denotes the row and column (in that order). If the starting position is already occupied by a celestial body, the program should print out Invalid starting position!. Then the program should prompt with Re-enter starting position: and re-scan the position of the player, repeating until a valid position is scanned in.

  2. After spawning the player, the program should prompt for stars with Enter the position and points of the star(s): and take input in the form [row] [col] [points] until ctrl + D is pressed. Again, you may assume that the provided input is always valid.

  3. Finally, after spawning all celestial bodies, the program should print the galaxy with the print_galaxy function provided.

This program is the starting point we'll be using today:

// part1_galaxy.c
//
// This program was written by YOUR-NAME (ZID)
// on DATE
//
// This program is a simple game that allows the user to build a galaxy. 
// The user can place stars, planets, and nebulae in the galaxy.

#include <stdio.h>

#define SIZE 5
#define NEBULA_POINTS -10

enum entity {
    STAR,
    PLANET,
    NEBULA,
    SPACESHIP,
    EMPTY,
};

struct celestial_body {
    enum entity entity;
    int points;
};

void print_map(struct celestial_body galaxy[SIZE][SIZE]);

int main(void) {
    struct celestial_body galaxy[SIZE][SIZE];

    // TODO: Initialize the galaxy

    // TODO: Place the planets and nebulae in the galaxy
    printf("Enter planets and nebulae:\n");

    // TODO: Place the player in the galaxy
    printf("Enter the starting position of the player: ");

    // TODO: Place the stars in the galaxy
    printf("Enter the position and points of the star(s):\n");

    // TODO: Print the map

    return 0;
}

// Function prints the map of the galaxy
// 
// Parameters:
// - galaxy: the 2D array representing the galaxy
//
// returns: nothing
void print_map(struct celestial_body galaxy[SIZE][SIZE]) {
    printf("\n---------------------\n");
    for (int i = 0; i < SIZE; i++) {
        for (int j = 0; j < SIZE; j++) {
            printf("|");
            if (galaxy[i][j].entity == SPACESHIP) {
                printf(" X ");
            } else if (galaxy[i][j].entity == EMPTY) {
                printf("   ");
            } else if (galaxy[i][j].entity == STAR) {
                printf(" * ");
            } else if (galaxy[i][j].entity == PLANET) {
                printf(" o ");
            } else if (galaxy[i][j].entity == NEBULA) {
                printf(" # ");
            }
        }
        printf("|\n");
        printf("---------------------\n");
    }
}

Part 2: Arrays and Functions (15 min max)

In this section, we'll practice writing and using functions, focusing in particular on how they interact with arrays.

To do this we will be working with the program we created in part1 and in groups refactoring the program to use functions.

Part 3: Strings (20 min max)

Warmup:

Your tutor may briefly run through the following code and diagram with you:

Diagram of strings in c


// part3_simple_string.c
//
// This program was written by Sofia De Bellis (z5418801)
// on March 2024
//
// This program demonstrates how to work with strings in C.

#include <stdio.h>

#define MAX_SIZE 1024

int main(void) {
    // Declare and initialise a string
    char my_string[] = "Hello world!";
    
    // Traverse the string and print each character
    int i = 0;
    while (my_string[i] != '\0') {
        printf("%c", my_string[i]);
        i++;
    }
    printf("\n");

    // Another way to traverse the string and print each character 
    for (int i = 0; my_string[i] != '\0'; i++) {
        printf("%c", my_string[i]);
    }

    // How to print a string in its entirety
    printf("My string: %s\n", my_string);

    // Declare a string
    char another_string[MAX_SIZE];
    
    // Read a string from the user, note we DO NOT use scanf for strings
    printf("Enter a string: ");
    fgets(another_string, MAX_SIZE, stdin);
    
    // Print the string using fputs
    fputs(another_string, stdout);

    return 0;
}

Practice

In this section you'll be completing some string activities in your groups.

Have a quick look at the following char functions that have been implemented for you:

// Provided char functions

// Returns : 1 if `c` is a lowercase letter
//         : 0 otherwise.
int is_lowercase(char c) {

    return 'a' <= c && c <= 'z';
}

// Returns : 1 if `c` is an uppercase letter
//         : 0 otherwise.
int is_uppercase(char c) {

    return 'A' <= c && c <= 'Z';
}

// Returns : 1 if `c` is a letter
//         : 0 otherwise.
int is_letter(char c) {

    return is_lowercase(c) || is_uppercase(c);
}

// Returns : `c` converted to lowercase, if it was an uppercase letter
//         : `c` unmodified, otherwise
char to_lowercase(char c) {
    if (is_uppercase(c)) {
        return c - 'A' + 'a';
    }

    return c;
}

// Returns : `c` converted to uppercase, if it was a lowercase letter
//         : `c` unmodified, otherwise
char to_uppercase(char c) {
    if (is_lowercase(c)) {
        return c - 'a' + 'A';
    }

    return c;
}

// Returns : 1 if `c` is an uppercase or lowercase vowel
//         : 0 otherwise.
int is_vowel(char c) {
    char lower_c = to_lowercase(c);

    return lower_c == 'a' 
        || lower_c == 'e'
        || lower_c == 'i' 
        || lower_c == 'o' 
        || lower_c == 'u';
}

You may want to use some of these in your solutions.

You will be completing one of these functions!

// Functions to implement:

// 1.
// returns the number of lowercase letters in `char *string`
int count_lowercase(char string[MAX_CHARS]) {
    return 42;
}

// 2.
// modifies `char *string` by converting all its vowels to uppercase
void make_vowels_uppercase(char string[MAX_CHARS]) {
    return;
}

// 3..
// shortens a string so that it ends after the first word
// e.g. "This is a sentence" should turn into:
//      "This"
// 
// (hint. what defines when a string ends?)
void delete_following_words(char string[MAX_CHARS]) {
    return;
}