Programming Fundamentals

Information

  • This page contains additional revision exercises for week 08.
  • These exercises are not compulsory, nor do they provide any marks in the course.
  • You cannot submit any of these exercises, however autotests may be available for some them (Command included at bottom of each exercise if applicable).

Revision Video: Pointers - Motivation for Learning

Revision Video: Pointers - Walkthrough using a swap function

Revision Video: Pointers - Walkthrough (Coding)

Revision Video: Dynamic Memory Allocation - Motivation for Learning

Revision Video: Dynamic Memory Allocation - Walkthrough (Coding)

Revision Video: Linked Lists - Prerequisites

Revision Video: Linked Lists - Creating and traversing a linked list (Coding)

Revision Video: Linked List - Sorted Insert

Revision Video: Linked Lists - Adding elements to a Linked List (Coding)

Revision Video: Linked List - Delete

Revision Video: Linked Lists - Deleting elements from a Linked List (Coding)

Exercise — individual:
Debugging Exercise -- Room Service

Download room_service.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity room_service

Before writing any code, your tutor will walk you through a short activity exploring the difference between functions that use pointers and functions that don't.

Your task is to fix any bugs in the starter code room_service.c so that the program works as intended.

The program should:

  • Read in a number of snacks to deliver to Sasha and a number of snacks to deliver to Henry.
  • Call deliver() to add the snacks to each room. The function should remain as a void function.
  • Print the new total number of snacks in each room.

Expected Output

dcc room_service.c -o room_service
./room_service
Enter the number of snacks to deliver to Sasha's room: 3
Enter the number of snacks to deliver to Henry's room: 5
Sasha's room now has 5 snacks.
Henry's room now has 9 snacks.

Assumptions/Restrictions/Clarifications

  • No error checking is needed.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest room_service

Exercise — individual:
Game Lag Reports

Download game_lags.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity game_lags

Your task is to complete game_lags.c using the provided starter code. Each command-line argument represents one recorded lag, given as its duration in milliseconds.

The program should:

  • Prompt the user with "Enter the maximum acceptable lag in milliseconds: " and read a single integer. Any recorded lag with a duration greater than or equal to this integer is considered a lag spike.
  • Count how many of the recorded lags are lag spikes.
  • If there are no lag spikes, print "No lag spikes recorded!\n" and return from main.
  • Otherwise, malloc a new array to hold all the lag spikes.
  • Pass this array to the provided average_lag and worst_lag functions to build a short report, printing:
    • "Number of lag spikes: %d\n"
    • "Average lag spike duration: %.2f ms\n"
    • "Worst lag spike duration: %d ms\n"
  • Free the array once you're done with it.

Examples

dcc game_lags.c -o game_lags
./game_lags 20 55 12 80 5
Enter the maximum acceptable lag in milliseconds: 30
Number of lag spikes: 2
Average lag spike duration: 67.50 ms
Worst lag spike duration: 80 ms
./game_lags 5 10 15
Enter the maximum acceptable lag in milliseconds: 50
No lag spikes recorded!

Assumptions/Restrictions/Clarifications

  • You may assume at least one lag duration will be provided as a command-line argument.
  • You may assume every command-line argument is a valid non-negative integer.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest game_lags

Exercise — individual:
Pottery Studio

Download pottery_studio.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity pottery_studio

Pottery has to pass through several stages before it's ready to sell. All pieces will start as soft, freshly-thrown greenware, through leather-hard and a bisque firing, to a final glaze firing that makes it ready for the shelf.

Your task is to complete the program pottery_studio.c using the provided starter code. The program simulates a small pottery studio, tracking pieces as they move through these stages using two linked lists: progress_pieces (pieces still being worked on) and pieces_for_sale (pieces that have finished glaze firing).

You should implement three functions:

  • create_piece: allocates and returns a new struct ceramic_piece with the given name.
    • All pieces will start at the GREENWARE stage.
  • add_piece: creates a new piece with the given name and appends it to the end of studio->progress_pieces.
  • fire_pieces: advances every piece in studio->progress_pieces forward by one stage
    • The stage progression is: GREENWARELEATHER_HARDBISQUE_FIREDGLAZE_FIRED).
    • Any piece that reaches GLAZE_FIRED during this firing is finished, and should be removed from progress_pieces and appended to the end of pieces_for_sale instead.
  • free_studio: frees every piece in both progress_pieces and pieces_for_sale, as well as the studio struct itself.

The provided print_studio, print_pieces, and stage_to_string functions handle all the output for you.

Example

dcc pottery_studio.c -o pottery_studio
./pottery_studio
=== Initial Studio ===
Pieces in progress:
  Tea Bowl        GREENWARE
  Coffee Mug      GREENWARE

Pieces for sale:
  (none)

=== After Firing 1 ===
Pieces in progress:
  Tea Bowl        LEATHER_HARD
  Coffee Mug      LEATHER_HARD

Pieces for sale:
  (none)

=== After Firing 2 ===
Pieces in progress:
  Tea Bowl        BISQUE_FIRED
  Coffee Mug      BISQUE_FIRED
  Vase            LEATHER_HARD

Pieces for sale:
  (none)

=== After Firing 3 ===
Pieces in progress:
  Vase            BISQUE_FIRED
  Bowl            LEATHER_HARD

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED

=== After Firing 4 ===
Pieces in progress:
  Bowl            BISQUE_FIRED

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED
  Vase            GLAZE_FIRED

=== After Firing 5 ===
Pieces in progress:
  (none)

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED
  Vase            GLAZE_FIRED
  Bowl            GLAZE_FIRED

Assumptions/Restrictions/Clarifications

  • No error checking is needed.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest pottery_studio

Exercise — individual:
Mini Linter

Download mini_linter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity mini_linter

Before splitting into groups, your tutor will live-code a small demo of mini_linter_comments.c, which strips any inline // comment from a line of code.

Each of the programs below will:

  • Read lines of "code" from standard input, until [Ctrl-D] is pressed.
  • For each line, a result will be printed depending on the role of the program, as outlined below.

1. Removing Inline Comments (Tutor Demo)

Complete remove_inline_comments so that it removes an inline // comment from line, if one is present.

// mini_linter_comments.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Tutor demo: Removes inline comments from a line of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void remove_inline_comments(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        remove_inline_comments(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Removes any inline comments from the provided line
void remove_inline_comments(char *line) {
    // TODO: Follow along as your tutor demonstrates this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_comments.c -o mini_linter_comments
./mini_linter_comments
Enter lines of code:
int flag = 1; // this is a flag
int flag = 1; 
int total = 0;
int total = 0;
[Ctrl-D]

2. Adding Missing Semicolons

Complete add_semicolon so that it adds a semicolon to the end of line, if one isn't already there.

// mini_linter_semicolon.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Adds missing semicolons to lines of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void add_semicolon(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        add_semicolon(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Adds any missing semicolon to the end of the provided line.
void add_semicolon(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_semicolon.c -o mini_linter_semicolon
./mini_linter_semicolon
Enter lines of code:
int x = 5
int x = 5;
int y = 10;
int y = 10;
[Ctrl-D]

3. Removing Trailing Spaces

Complete remove_trailing_spaces so that it removes any trailing spaces from the end of line.

// mini_linter_trailing_spaces.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Removes trailing spaces from lines of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void remove_trailing_spaces(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        remove_trailing_spaces(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Removes any trailing spaces from the provided line. 
void remove_trailing_spaces(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_trailing_spaces.c -o mini_linter_trailing_spaces
./mini_linter_trailing_spaces
Enter lines of code:
int y = 10;   
int y = 10;
int z = 20;
int z = 20;
[Ctrl-D]

4. Checking Operator Whitespace

Complete missing_operand_whitespace so that it returns 1 if any of the operators +, -, *, /, % or = in line is missing whitespace on either side of it, and 0 otherwise.

// mini_linter_operator_whitespace.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Detects operators without whitespace around them.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

int missing_operand_whitespace(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        if (missing_operand_whitespace(line)) {
            printf("Missing whitespace around an operator!\n");
        } else {
            printf("No issues found.\n");
        }
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Checks if any operands (* - + / % =) have any missing whitespace around them.
// Returns 1 if there is missing whitespace, and 0 otherwise.
int missing_operand_whitespace(char *line) {
    // TODO: Complete this function

    return 0;
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_operator_whitespace.c -o mini_linter_operator_whitespace
./mini_linter_operator_whitespace
Enter lines of code:
int total = a+b;
Missing whitespace around an operator!
int total =a + b;
Missing whitespace around an operator!
int total = a + b;
No issues found.
[Ctrl-D]

5. Splitting Long Lines

Complete split_long_line so that, if line is longer than 80 characters, it's split into two lines by replacing the closest space at or before position 80 with a newline character.

// mini_linter_split_line.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Splits long lines over 80 characters.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void split_long_line(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        split_long_line(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Splits long lines by replacing the closest whitespace before 80 characters
// with a newline character.
void split_long_line(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_split_line.c -o mini_linter_split_line
./mini_linter_split_line
Enter lines of code:
int total = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
int total = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 +
16;
short line;
short line;
[Ctrl-D]

Assumptions/Restrictions/Clarifications

  • No error checking is required.
  • You may assume no line will ever be longer than 160 characters.
  • missing_operand_whitespace only needs to check the operators +, -, *, /, % and =.
  • For split_long_line, you may assume there will always be a space at or before position 80 in line.
  • All programs that are required to modify the provided line should make these modifications in place. This means line itself should be modified, without creating any copies.

Exercise
(●◌◌)
:

Sea Creature Sanctuary

Download sea_creatures.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity sea_creatures

The ocean research centre needs a program to track the sea creatures its divers discover. Since creatures can be added and released at any time, they need a home in memory that isn't fixed in place. malloc lets you create exactly that!

Your task is to complete sea_creatures.c by implementing two functions:

  1. create_creature: Creates a new struct creature using malloc, initialising its name and size fields with the provided arguments, then returns a pointer to the new creature.
  2. release_creature: Frees the memory used by a creature when it is no longer needed.

Example

dcc sea_creatures.c -o sea_creatures --leak-check
./sea_creatures
Enter creature name: Blue Whale
Enter creature size: 2500

Creating creature...

Creature details:
Name: Blue Whale
Size: 2500

Releasing creature...

Assumptions/Restrictions/Clarifications

  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest sea_creatures

Exercise
(●◌◌)
:

Debugging Exercise -- Broken Inventory

Download broken_inventory.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity broken_inventory

Your task is to find and fix the bugs in broken_inventory.c so that the inventory system works as intended, without crashing and without leaking memory.

HINT: There will be a bug in each of the functions:

  • create_item: creates a new item and returns a pointer to it.
  • append_item: creates and appends a new item to the inventory and returns the updated head of the inventory list.
  • use_item: "uses" an item that matches the given name by decreasing its quantity by 1. If the quantity reaches 0, the item is removed from the inventory.
  • free_items: frees all memory associated with the inventory.

Debugging Tips

Some debugging tips for you:

  • dcc output: as you run into issues, dcc will point you to where the errors are. It gives you the line number the issue is on along with some explanation, so make sure you read everything it tells you.
  • Not every bug is a compiler error: a program can compile with zero warnings and still crash, or leak memory. If your program runs but crashes partway through, trace through the code by hand to work out exactly which line causes it.
  • --leak-check: always compile with this flag for this activity. A leak won't crash your program or produce any visibly wrong output — it will only show up as a leak-check warning at the end of a run.
  • COMP1511 debugging guide

Examples

dcc broken_inventory.c -o broken_inventory --leak-check
./broken_inventory
== Starting inventory ==
====== Inventory ======
    Potion x3
    Sword x1

Using the Potion.
====== Inventory ======
    Potion x2
    Sword x1

Using the Sword.
====== Inventory ======
    Potion x2

Assumptions/Restrictions/Clarifications

  • You should not need to modify main or print_inventory.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest broken_inventory

Exercise
(●◌◌)
:

Calm Down!

Download calm_down.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity calm_down

Sometimes a message could really use fewer exclamation marks!!! Your job is to write a "calm down" filter that tones down an overly enthusiastic message.

Complete the program calm_down.c, which:

  • Prompts the user to enter a string with Enter a message: .
  • Scans in the string from stdin.
  • Replaces every '!' character with a '.', modifying the string in place.
  • Prints the modified string to stdout.

Example

dcc calm_down.c -o calm_down
./calm_down
Enter a message: This is amazing!!! I can't believe it!!
This is amazing... I can't believe it..

Assumptions/Restrictions/Clarifications

  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest calm_down

Exercise
(●●◌)
:

Sum of Positive and Negative Numbers

Download sum_of_positive_negative.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity sum_of_positive_negative

Your task is to implement the function sum_of_positive_negative in the provided starter code sum_of_positive_negative.c.

The function should:

  • Calculate the sum of all positive numbers in the linked list, and store it in *positive_sum.
  • Calculate the sum of all negative numbers in the linked list, and store it in *negative_sum.

The construction of the linked list from command line arguments has been provided for you.

Examples

dcc sum_of_positive_negative.c -o sum_of_positive_negative
./sum_of_positive_negative 1 -2 3 -4 5
LIST: 1 -> -2 -> 3 -> -4 -> 5 -> NULL
Positive sum: 9
Negative sum: -6
./sum_of_positive_negative 8 10 4 2 1
LIST: 8 -> 10 -> 4 -> 2 -> 1 -> NULL
Positive sum: 25
Negative sum: 0
./sum_of_positive_negative -5 -1 -3 -4
LIST: -5 -> -1 -> -3 -> -4 -> NULL
Positive sum: 0
Negative sum: -13

Assumptions/Restrictions/Clarifications

  • If the linked list is empty, both positive_sum and negative_sum should be 0.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest sum_of_positive_negative

Exercise
(●●◌)
:

Route Setter

Download route_setter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity route_setter

Your task is to complete the program route_setter.c using the provided starter code.

A main function and a series of helper functions have been implemented for you. The program allows a climber to interactively build and analyse a bouldering route using commands. However, the functions that manipulate the linked list are currently incomplete.

You must implement the following functions:

  1. append_hold

    • Add a new hold at the end of the route.
    • The new hold should store the provided new_hold_id and difficulty.
  2. insert_after_hold

    • Add a new hold into the route immediately after the hold with the given hold_id.
    • The new hold should store the provided new_hold_id and difficulty.
  3. remove_hold

    • Remove the hold with the given hold_id from the route.
    • Remember to free any memory that is no longer needed.
  4. find_crux

    • Find and return a pointer to the hardest hold in the route.
    • The crux is the hold with the highest difficulty.
  5. climber_progress

    • Given a climber's skill level, determine how many holds they can complete in order before encountering a hold that is too difficult.
    • A climber can complete a hold if its difficulty is less than or equal to their skill level.
    • Return the number of holds completed.

The provided create_hold, print_route, print_commands, and free_route functions handle creating, displaying, and freeing the linked list for you.

Example

dcc route_setter.c -o route_setter
./route_setter
Welcome to Route Setter!
a 1 2
a 2 4
a 3 7
a 4 3
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 3 (difficulty 7)
Hold 4 (difficulty 3)
i 2 99 5
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 99 (difficulty 5)
Hold 3 (difficulty 7)
Hold 4 (difficulty 3)
r 3
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 99 (difficulty 5)
Hold 4 (difficulty 3)
x
Crux hold is 99 (difficulty 5)
c 4
A climber with skill 4 can climb 2 holds before failing.
q

Assumptions/Restrictions/Clarifications

  • No error checking is required.
  • You may assume that all ids are unique.
  • You may assume that all commands are valid.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest route_setter

Exercise
(●●●)
:

Extension -- Chaotic Route Setter

Download chaotic_route_setter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity chaotic_route_setter

Your task is to complete the program chaotic_route_setter.c by extending your solution to route_setter.c to implement a new shuffle route command.

The shuffle route command is called when the user types s into the command loop, with no additional arguments. When called, the program should:

  • Split the climb into two halves: the first half and the second half.
  • Recombine the two halves by zipping them together. This means alternating one hold from the first half, then one hold from the second half, repeating until both halves are exhausted.

For example, given the climb [1, 2, 3, 4, 5, 6], the first half is [1, 2, 3] and the second half is [4, 5, 6]. Zipping them together produces [1, 4, 2, 5, 3, 6].

As an extra challenge, attempt this task without allocating any new memory.

The provided starter code, chaotic_route_setter.c, is mostly the same as route_setter.c, but with some minor changes:

  • The command_loop function will need to be modified to recognise the shuffle route command.
  • There is an added function stub and prototype for shuffle_route to implement the shuffling logic. You may want to use this starter code, and copy over your function implementations from route_setter.c.

Example

dcc chaotic_route_setter.c -o chaotic_route_setter
./chaotic_route_setter
Welcome to Route Setter!
a 1 1
a 2 2
a 3 3
a 4 4
a 5 5
a 6 6
p
==== Current Route ====
Hold 1 (difficulty 1)
Hold 2 (difficulty 2)
Hold 3 (difficulty 3)
Hold 4 (difficulty 4)
Hold 5 (difficulty 5)
Hold 6 (difficulty 6)
s
p
==== Current Route ====
Hold 1 (difficulty 1)
Hold 4 (difficulty 4)
Hold 2 (difficulty 2)
Hold 5 (difficulty 5)
Hold 3 (difficulty 3)
Hold 6 (difficulty 6)
q

Assumptions/Restrictions/Clarifications

  • If a route contains an odd number of holds, the first half should contain one more hold than the second half.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest chaotic_route_setter

Exercise
(●●●)
:

Extension -- Advanced Linter

Download advanced_linter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity advanced_linter

This activity extends the mini linter exercise from the revision session.

Previously, your linter could perform a single modification to a line of code. Your task is now to implement a more capable linter by completing several string manipulation functions.

The program repeatedly reads lines of code from standard input until [CTRL-D] is entered.

For every line, the following functions should be applied in order:

  1. collapse_whitespace
    • Replace consecutive spaces with a single space.
    • It should not collapse any leading spaces (at the start of the line) as this may be valid indentation.
  2. add_operator_spacing
    • Ensure every =, +, -, * and / has a single space on either side.
  3. wrap_long_lines
    • If a line exceeds 80 characters, replace the last whitespace before the 80th character with a newline followed by a tab character ('\n' then '\t').
    • Continue wrapping until every line is at most 80 characters long.

The provided print_result function will display the final linted line.

Example

dcc advanced_linter.c -o advanced_linter
./advanced_linter
Enter lines of code:
int    x     =      5;
int x = 5;
a =b+c*d/e-f
a = b + c * d / e - f
this is a deliberately very long line that should be wrapped multiple times because it contains far more than eighty characters before reaching the end of the sentence now we go again to show multi wrap this is a deliberately very long line that should be wrapped multiple times because it contains far more than eighty characters before reaching the end of the sentence
this is a deliberately very long line that should be wrapped multiple times
        because it contains far more than eighty characters before reaching the end of the
        sentence now we go again to show multi wrap this is a deliberately very long
        line that should be wrapped multiple times because it contains far more than
        eighty characters before reaching the end of the sentence
int    total=apples+oranges+bananas+pears+grapes+watermelons+pineapples;
int total = apples + oranges + bananas + pears + grapes + watermelons +
        pineapples;
[CTRL-D]

Assumptions/Restrictions/Clarifications

  • You may assume every input line is at most 1000 characters long.
  • You may assume that for wrap_long_lines, there will always be a whitespace before the 80th character.
  • You may assume operators never appear at the beginning or end of a line.
  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest advanced_linter

Exercise — individual:
Debugging Exercise -- Room Service

Download room_service.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity room_service

Before writing any code, your tutor will walk you through a short activity exploring the difference between functions that use pointers and functions that don't.

Your task is to fix any bugs in the starter code room_service.c so that the program works as intended.

The program should:

  • Read in a number of snacks to deliver to Sasha and a number of snacks to deliver to Henry.
  • Call deliver() to add the snacks to each room. The function should remain as a void function.
  • Print the new total number of snacks in each room.

Expected Output

dcc room_service.c -o room_service
./room_service
Enter the number of snacks to deliver to Sasha's room: 3
Enter the number of snacks to deliver to Henry's room: 5
Sasha's room now has 5 snacks.
Henry's room now has 9 snacks.

Assumptions/Restrictions/Clarifications

  • No error checking is needed.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest room_service

Exercise — individual:
Game Lag Reports

Download game_lags.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity game_lags

Your task is to complete game_lags.c using the provided starter code. Each command-line argument represents one recorded lag, given as its duration in milliseconds.

The program should:

  • Prompt the user with "Enter the maximum acceptable lag in milliseconds: " and read a single integer. Any recorded lag with a duration greater than or equal to this integer is considered a lag spike.
  • Count how many of the recorded lags are lag spikes.
  • If there are no lag spikes, print "No lag spikes recorded!\n" and return from main.
  • Otherwise, malloc a new array to hold all the lag spikes.
  • Pass this array to the provided average_lag and worst_lag functions to build a short report, printing:
    • "Number of lag spikes: %d\n"
    • "Average lag spike duration: %.2f ms\n"
    • "Worst lag spike duration: %d ms\n"
  • Free the array once you're done with it.

Examples

dcc game_lags.c -o game_lags
./game_lags 20 55 12 80 5
Enter the maximum acceptable lag in milliseconds: 30
Number of lag spikes: 2
Average lag spike duration: 67.50 ms
Worst lag spike duration: 80 ms
./game_lags 5 10 15
Enter the maximum acceptable lag in milliseconds: 50
No lag spikes recorded!

Assumptions/Restrictions/Clarifications

  • You may assume at least one lag duration will be provided as a command-line argument.
  • You may assume every command-line argument is a valid non-negative integer.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest game_lags

Exercise — individual:
Pottery Studio

Download pottery_studio.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity pottery_studio

Pottery has to pass through several stages before it's ready to sell. All pieces will start as soft, freshly-thrown greenware, through leather-hard and a bisque firing, to a final glaze firing that makes it ready for the shelf.

Your task is to complete the program pottery_studio.c using the provided starter code. The program simulates a small pottery studio, tracking pieces as they move through these stages using two linked lists: progress_pieces (pieces still being worked on) and pieces_for_sale (pieces that have finished glaze firing).

You should implement three functions:

  • create_piece: allocates and returns a new struct ceramic_piece with the given name.
    • All pieces will start at the GREENWARE stage.
  • add_piece: creates a new piece with the given name and appends it to the end of studio-&gt;progress_pieces.
  • fire_pieces: advances every piece in studio-&gt;progress_pieces forward by one stage
    • The stage progression is: GREENWARELEATHER_HARDBISQUE_FIREDGLAZE_FIRED).
    • Any piece that reaches GLAZE_FIRED during this firing is finished, and should be removed from progress_pieces and appended to the end of pieces_for_sale instead.
  • free_studio: frees every piece in both progress_pieces and pieces_for_sale, as well as the studio struct itself.

The provided print_studio, print_pieces, and stage_to_string functions handle all the output for you.

Example

dcc pottery_studio.c -o pottery_studio
./pottery_studio
=== Initial Studio ===
Pieces in progress:
  Tea Bowl        GREENWARE
  Coffee Mug      GREENWARE

Pieces for sale:
  (none)

=== After Firing 1 ===
Pieces in progress:
  Tea Bowl        LEATHER_HARD
  Coffee Mug      LEATHER_HARD

Pieces for sale:
  (none)

=== After Firing 2 ===
Pieces in progress:
  Tea Bowl        BISQUE_FIRED
  Coffee Mug      BISQUE_FIRED
  Vase            LEATHER_HARD

Pieces for sale:
  (none)

=== After Firing 3 ===
Pieces in progress:
  Vase            BISQUE_FIRED
  Bowl            LEATHER_HARD

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED

=== After Firing 4 ===
Pieces in progress:
  Bowl            BISQUE_FIRED

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED
  Vase            GLAZE_FIRED

=== After Firing 5 ===
Pieces in progress:
  (none)

Pieces for sale:
  Tea Bowl        GLAZE_FIRED
  Coffee Mug      GLAZE_FIRED
  Vase            GLAZE_FIRED
  Bowl            GLAZE_FIRED

Assumptions/Restrictions/Clarifications

  • No error checking is needed.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest pottery_studio

Exercise — individual:
Mini Linter

Download mini_linter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity mini_linter

Before splitting into groups, your tutor will live-code a small demo of mini_linter_comments.c, which strips any inline // comment from a line of code.

Each of the programs below will:

  • Read lines of "code" from standard input, until [Ctrl-D] is pressed.
  • For each line, a result will be printed depending on the role of the program, as outlined below.

1. Removing Inline Comments (Tutor Demo)

Complete remove_inline_comments so that it removes an inline // comment from line, if one is present.

// mini_linter_comments.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Tutor demo: Removes inline comments from a line of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void remove_inline_comments(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        remove_inline_comments(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Removes any inline comments from the provided line
void remove_inline_comments(char *line) {
    // TODO: Follow along as your tutor demonstrates this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_comments.c -o mini_linter_comments
./mini_linter_comments
Enter lines of code:
int flag = 1; // this is a flag
int flag = 1; 
int total = 0;
int total = 0;
[Ctrl-D]

2. Adding Missing Semicolons

Complete add_semicolon so that it adds a semicolon to the end of line, if one isn't already there.

// mini_linter_semicolon.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Adds missing semicolons to lines of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void add_semicolon(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        add_semicolon(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Adds any missing semicolon to the end of the provided line.
void add_semicolon(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_semicolon.c -o mini_linter_semicolon
./mini_linter_semicolon
Enter lines of code:
int x = 5
int x = 5;
int y = 10;
int y = 10;
[Ctrl-D]

3. Removing Trailing Spaces

Complete remove_trailing_spaces so that it removes any trailing spaces from the end of line.

// mini_linter_trailing_spaces.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Removes trailing spaces from lines of code.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void remove_trailing_spaces(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        remove_trailing_spaces(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Removes any trailing spaces from the provided line. 
void remove_trailing_spaces(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_trailing_spaces.c -o mini_linter_trailing_spaces
./mini_linter_trailing_spaces
Enter lines of code:
int y = 10;   
int y = 10;
int z = 20;
int z = 20;
[Ctrl-D]

4. Checking Operator Whitespace

Complete missing_operand_whitespace so that it returns 1 if any of the operators +, -, *, /, % or = in line is missing whitespace on either side of it, and 0 otherwise.

// mini_linter_operator_whitespace.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Detects operators without whitespace around them.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

int missing_operand_whitespace(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        if (missing_operand_whitespace(line)) {
            printf("Missing whitespace around an operator!\n");
        } else {
            printf("No issues found.\n");
        }
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Checks if any operands (* - + / % =) have any missing whitespace around them.
// Returns 1 if there is missing whitespace, and 0 otherwise.
int missing_operand_whitespace(char *line) {
    // TODO: Complete this function

    return 0;
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_operator_whitespace.c -o mini_linter_operator_whitespace
./mini_linter_operator_whitespace
Enter lines of code:
int total = a+b;
Missing whitespace around an operator!
int total =a + b;
Missing whitespace around an operator!
int total = a + b;
No issues found.
[Ctrl-D]

5. Splitting Long Lines

Complete split_long_line so that, if line is longer than 80 characters, it's split into two lines by replacing the closest space at or before position 80 with a newline character.

// mini_linter_split_line.c
//
// Written by YOUR-NAME (YOUR-ZID)
// on TODAYS-DATE
//
// Splits long lines over 80 characters.

#include <stdio.h>
#include <string.h>

#define MAX_LINE_LENGTH 161

void split_long_line(char *line);
void remove_newline(char *line);

// -----------------------------------------------------------------------------

int main(void) {
    char line[MAX_LINE_LENGTH];

    printf("Enter lines of code:\n");

    while (fgets(line, MAX_LINE_LENGTH, stdin) != NULL) {
        remove_newline(line);
        split_long_line(line);
        printf("%s\n", line);
    }

    return 0;
}

// -----------------------------------------------------------------------------
// YOUR FUNCTION
// -----------------------------------------------------------------------------

// Splits long lines by replacing the closest whitespace before 80 characters
// with a newline character.
void split_long_line(char *line) {
    // TODO: Complete this function
}

// -----------------------------------------------------------------------------
// PROVIDED FUNCTIONS
// -----------------------------------------------------------------------------
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////////

// Helper function to remove the newline character from the end of a string
void remove_newline(char *line) {
    int i = 0;
    while (line[i] != '\n' && line[i] != '\0') {
        i++;
    }
    line[i] = '\0';
}
Example
dcc mini_linter_split_line.c -o mini_linter_split_line
./mini_linter_split_line
Enter lines of code:
int total = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
int total = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 +
16;
short line;
short line;
[Ctrl-D]

Assumptions/Restrictions/Clarifications

  • No error checking is required.
  • You may assume no line will ever be longer than 160 characters.
  • missing_operand_whitespace only needs to check the operators +, -, *, /, % and =.
  • For split_long_line, you may assume there will always be a space at or before position 80 in line.
  • All programs that are required to modify the provided line should make these modifications in place. This means line itself should be modified, without creating any copies.

Exercise
(●◌◌)
:

Sea Creature Sanctuary

Download sea_creatures.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity sea_creatures

The ocean research centre needs a program to track the sea creatures its divers discover. Since creatures can be added and released at any time, they need a home in memory that isn't fixed in place. malloc lets you create exactly that!

Your task is to complete sea_creatures.c by implementing two functions:

  1. create_creature: Creates a new struct creature using malloc, initialising its name and size fields with the provided arguments, then returns a pointer to the new creature.
  2. release_creature: Frees the memory used by a creature when it is no longer needed.

Example

dcc sea_creatures.c -o sea_creatures --leak-check
./sea_creatures
Enter creature name: Blue Whale
Enter creature size: 2500

Creating creature...

Creature details:
Name: Blue Whale
Size: 2500

Releasing creature...

Assumptions/Restrictions/Clarifications

  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest sea_creatures

Exercise
(●◌◌)
:

Debugging Exercise -- Broken Inventory

Download broken_inventory.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity broken_inventory

Your task is to find and fix the bugs in broken_inventory.c so that the inventory system works as intended, without crashing and without leaking memory.

HINT: There will be a bug in each of the functions:

  • create_item: creates a new item and returns a pointer to it.
  • append_item: creates and appends a new item to the inventory and returns the updated head of the inventory list.
  • use_item: "uses" an item that matches the given name by decreasing its quantity by 1. If the quantity reaches 0, the item is removed from the inventory.
  • free_items: frees all memory associated with the inventory.

Debugging Tips

Some debugging tips for you:

  • dcc output: as you run into issues, dcc will point you to where the errors are. It gives you the line number the issue is on along with some explanation, so make sure you read everything it tells you.
  • Not every bug is a compiler error: a program can compile with zero warnings and still crash, or leak memory. If your program runs but crashes partway through, trace through the code by hand to work out exactly which line causes it.
  • --leak-check: always compile with this flag for this activity. A leak won't crash your program or produce any visibly wrong output — it will only show up as a leak-check warning at the end of a run.
  • COMP1511 debugging guide

Examples

dcc broken_inventory.c -o broken_inventory --leak-check
./broken_inventory
== Starting inventory ==
====== Inventory ======
    Potion x3
    Sword x1

Using the Potion.
====== Inventory ======
    Potion x2
    Sword x1

Using the Sword.
====== Inventory ======
    Potion x2

Assumptions/Restrictions/Clarifications

  • You should not need to modify main or print_inventory.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest broken_inventory

Exercise
(●◌◌)
:

Calm Down!

Download calm_down.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity calm_down

Sometimes a message could really use fewer exclamation marks!!! Your job is to write a "calm down" filter that tones down an overly enthusiastic message.

Complete the program calm_down.c, which:

  • Prompts the user to enter a string with Enter a message: .
  • Scans in the string from stdin.
  • Replaces every '!' character with a '.', modifying the string in place.
  • Prints the modified string to stdout.

Example

dcc calm_down.c -o calm_down
./calm_down
Enter a message: This is amazing!!! I can't believe it!!
This is amazing... I can't believe it..

Assumptions/Restrictions/Clarifications

  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest calm_down

Exercise
(●●◌)
:

Sum of Positive and Negative Numbers

Download sum_of_positive_negative.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity sum_of_positive_negative

Your task is to implement the function sum_of_positive_negative in the provided starter code sum_of_positive_negative.c.

The function should:

  • Calculate the sum of all positive numbers in the linked list, and store it in *positive_sum.
  • Calculate the sum of all negative numbers in the linked list, and store it in *negative_sum.

The construction of the linked list from command line arguments has been provided for you.

Examples

dcc sum_of_positive_negative.c -o sum_of_positive_negative
./sum_of_positive_negative 1 -2 3 -4 5
LIST: 1 -> -2 -> 3 -> -4 -> 5 -> NULL
Positive sum: 9
Negative sum: -6
./sum_of_positive_negative 8 10 4 2 1
LIST: 8 -> 10 -> 4 -> 2 -> 1 -> NULL
Positive sum: 25
Negative sum: 0
./sum_of_positive_negative -5 -1 -3 -4
LIST: -5 -> -1 -> -3 -> -4 -> NULL
Positive sum: 0
Negative sum: -13

Assumptions/Restrictions/Clarifications

  • If the linked list is empty, both positive_sum and negative_sum should be 0.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest sum_of_positive_negative

Exercise
(●●◌)
:

Route Setter

Download route_setter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity route_setter

Your task is to complete the program route_setter.c using the provided starter code.

A main function and a series of helper functions have been implemented for you. The program allows a climber to interactively build and analyse a bouldering route using commands. However, the functions that manipulate the linked list are currently incomplete.

You must implement the following functions:

  1. append_hold

    • Add a new hold at the end of the route.
    • The new hold should store the provided new_hold_id and difficulty.
  2. insert_after_hold

    • Add a new hold into the route immediately after the hold with the given hold_id.
    • The new hold should store the provided new_hold_id and difficulty.
  3. remove_hold

    • Remove the hold with the given hold_id from the route.
    • Remember to free any memory that is no longer needed.
  4. find_crux

    • Find and return a pointer to the hardest hold in the route.
    • The crux is the hold with the highest difficulty.
  5. climber_progress

    • Given a climber's skill level, determine how many holds they can complete in order before encountering a hold that is too difficult.
    • A climber can complete a hold if its difficulty is less than or equal to their skill level.
    • Return the number of holds completed.

The provided create_hold, print_route, print_commands, and free_route functions handle creating, displaying, and freeing the linked list for you.

Example

dcc route_setter.c -o route_setter
./route_setter
Welcome to Route Setter!
a 1 2
a 2 4
a 3 7
a 4 3
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 3 (difficulty 7)
Hold 4 (difficulty 3)
i 2 99 5
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 99 (difficulty 5)
Hold 3 (difficulty 7)
Hold 4 (difficulty 3)
r 3
p
==== Current Route ====
Hold 1 (difficulty 2)
Hold 2 (difficulty 4)
Hold 99 (difficulty 5)
Hold 4 (difficulty 3)
x
Crux hold is 99 (difficulty 5)
c 4
A climber with skill 4 can climb 2 holds before failing.
q

Assumptions/Restrictions/Clarifications

  • No error checking is required.
  • You may assume that all ids are unique.
  • You may assume that all commands are valid.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest route_setter

Exercise
(●●●)
:

Extension -- Chaotic Route Setter

Download chaotic_route_setter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity chaotic_route_setter

Your task is to complete the program chaotic_route_setter.c by extending your solution to route_setter.c to implement a new shuffle route command.

The shuffle route command is called when the user types s into the command loop, with no additional arguments. When called, the program should:

  • Split the climb into two halves: the first half and the second half.
  • Recombine the two halves by zipping them together. This means alternating one hold from the first half, then one hold from the second half, repeating until both halves are exhausted.

For example, given the climb [1, 2, 3, 4, 5, 6], the first half is [1, 2, 3] and the second half is [4, 5, 6]. Zipping them together produces [1, 4, 2, 5, 3, 6].

As an extra challenge, attempt this task without allocating any new memory.

The provided starter code, chaotic_route_setter.c, is mostly the same as route_setter.c, but with some minor changes:

  • The command_loop function will need to be modified to recognise the shuffle route command.
  • There is an added function stub and prototype for shuffle_route to implement the shuffling logic. You may want to use this starter code, and copy over your function implementations from route_setter.c.

Example

dcc chaotic_route_setter.c -o chaotic_route_setter
./chaotic_route_setter
Welcome to Route Setter!
a 1 1
a 2 2
a 3 3
a 4 4
a 5 5
a 6 6
p
==== Current Route ====
Hold 1 (difficulty 1)
Hold 2 (difficulty 2)
Hold 3 (difficulty 3)
Hold 4 (difficulty 4)
Hold 5 (difficulty 5)
Hold 6 (difficulty 6)
s
p
==== Current Route ====
Hold 1 (difficulty 1)
Hold 4 (difficulty 4)
Hold 2 (difficulty 2)
Hold 5 (difficulty 5)
Hold 3 (difficulty 3)
Hold 6 (difficulty 6)
q

Assumptions/Restrictions/Clarifications

  • If a route contains an odd number of holds, the first half should contain one more hold than the second half.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest chaotic_route_setter

Exercise
(●●●)
:

Extension -- Advanced Linter

Download advanced_linter.c here

Or, copy these file(s) to your CSE account using the following command:

1511 fetch-activity advanced_linter

This activity extends the mini linter exercise from the revision session.

Previously, your linter could perform a single modification to a line of code. Your task is now to implement a more capable linter by completing several string manipulation functions.

The program repeatedly reads lines of code from standard input until [CTRL-D] is entered.

For every line, the following functions should be applied in order:

  1. collapse_whitespace
    • Replace consecutive spaces with a single space.
    • It should not collapse any leading spaces (at the start of the line) as this may be valid indentation.
  2. add_operator_spacing
    • Ensure every =, +, -, * and / has a single space on either side.
  3. wrap_long_lines
    • If a line exceeds 80 characters, replace the last whitespace before the 80th character with a newline followed by a tab character ('\n' then '\t').
    • Continue wrapping until every line is at most 80 characters long.

The provided print_result function will display the final linted line.

Example

dcc advanced_linter.c -o advanced_linter
./advanced_linter
Enter lines of code:
int    x     =      5;
int x = 5;
a =b+c*d/e-f
a = b + c * d / e - f
this is a deliberately very long line that should be wrapped multiple times because it contains far more than eighty characters before reaching the end of the sentence now we go again to show multi wrap this is a deliberately very long line that should be wrapped multiple times because it contains far more than eighty characters before reaching the end of the sentence
this is a deliberately very long line that should be wrapped multiple times
        because it contains far more than eighty characters before reaching the end of the
        sentence now we go again to show multi wrap this is a deliberately very long
        line that should be wrapped multiple times because it contains far more than
        eighty characters before reaching the end of the sentence
int    total=apples+oranges+bananas+pears+grapes+watermelons+pineapples;
int total = apples + oranges + bananas + pears + grapes + watermelons +
        pineapples;
[CTRL-D]

Assumptions/Restrictions/Clarifications

  • You may assume every input line is at most 1000 characters long.
  • You may assume that for wrap_long_lines, there will always be a whitespace before the 80th character.
  • You may assume operators never appear at the beginning or end of a line.
  • No error checking is required.

When you think your program is working, you can use autotest to run some simple automated tests:

1511 autotest advanced_linter