Section 1

Section 1: Pointers and Strings #

How section works #

We release section material via the CS 300 website (where you’re reading this now) and the cs300-s25-section repository (obtain a local copy with a command like git clone git@github.com:csci0300/cs300-s25-section). Section instructors will work through the section material at their own pace, stopping at exercises, questions, and discussions so students can work through the material together. It’s best if you bring your laptop. Solutions for most section problems are available here, but you will learn more if you try to solve the problems yourself first.

Section works well if students ask questions, and sometimes instructors will take the section in an unexpected direction based on student requests. Please speak up! If you have questions from lecture, now’s the time to ask :-)

You can find the code for this section here!

Discussion: What's the Point? #

The course staff has some cool numbers they want to share with you in the following program! They're wondering if their numbers are cool enough.

void add_and_print1(int num) {
    num += 5;
    printf("The number is: %d\n", num);
}

void add_and_print2(int* num) {
    *num += 2;
    printf("The number is: %d\n", *num);
}

int main() {
    int cool_num = 10;

    add_and_print1(cool_num);

    add_and_print2(&cool_num);

    printf("%d\n", cool_num);

    return 0;
}

DISCUSSION A. Is add_print_1 pass by value or pass by reference?

DISCUSSION B. Is add_print_2 pass by value or pass by reference?

DISCUSSION C. What do you expect to be the output when main() executes?

Question 1: GDB Exploration #

Here's a program that does some operations and pointers and uses strings. It also has a bug! In this part, we'll learn more about C by exploring what this program does, and how we figure out where the bug is using the GNU debugger (GDB), which is a super-helpful tool to help you reason about programs!

In Section 1, Section 2, and many other projects and labs throughout the course, you'll be using GDB to help debug your programs. We'll use GDB to debug the program we just ran faster and cleaner!

int main()
{
    int the_num = 358296 - 87348 * 12345 / 91291 + 379969;
    int other_num = 0;

    if (the_num > 5000) {
        other_num = the_num;
    }
    else {
        other_num = the_num * 2;
    }

    char* the_string = "This is the first CS 300 section.";
    char fav_char = '!';
    dereference_and_set(&fav_char, '.');

    for (int i = 0; i < 7; i++) {
        the_string = strchr(the_string + 1, ' ');
    }

    dereference_and_set(the_string, '!');

    return 0;
}

QUESTION 1A. When the code runs, how can we figure out which branch of the if else statement will it execute? (Hint: this depends on the value of num)

QUESTION 1B. What is the value of the variable other_num?

QUESTION 1C. Unfortunately, when we run the program, it results in a segmentation fault! What line of code causes this segmentation fault and why?

QUESTION 1D. When in the for loop does smaller_string get set to a value that causes the segmentation fault?

Extra material #

The following problems are extra materials we have prepared that are relevant to this point in the course, but we don't plan on covering in section. Depending on how your section goes, we may refer to these problems if we need extra examples. Otherwise, feel free to use these as practice problems!

Extra: The Wizard's Spellbook (Bitwise Operators) #

The CS300 Wizard has found a novel way of organizing his spellbook---using bitwise operators! Unfortunately, he's more magic-savvy than he is tech-savvy, so he needs some help adding functionality.

The wizard's problem is that he's running out of spell points! After learning how to teleport, he can't learn any more!

The wizard used bitwise operators to add his new spells---can you help him remove them?

#define FIREBALL     0b001  // 1 - Cast Fireball
#define TELEPORT     0b010  // 2 - Teleport
#define INVISIBILITY 0b100  // 4 - Become Invisible

int main() {
    unsigned char wizard_spells = 0;
    
    // The wizard learns to cast fireball and teleport!
    wizard_spells = wizard_spells | FIREBALL;
    wizard_spells = wizard_spells | TELEPORT;

    // The wizard is running out of spell points, so he needs to forget teleport!
    // TODO: Write a line to forget TELEPORT

    // Check if the wizard still knows TELEPORT (shouldn't)
    if ((wizard_spells & TELEPORT) != 0) {
        printf("Bug detected! Wizard still knows TELEPORT!\n");
        exit(1);
    }

    // Check if the wizard still knows FIREBALL (should know)
    if ((wizard_spells & FIREBALL) == 0) {
        printf("Bug detected! Wizard forgot FIREBALL!\n");
        exit(1);
    }

    printf("Wizard's spells are correct!\n");
    return 0;
}

Extra: Tic-Tac-Toe Debugging #

In Section 1 and Section 2, you'll be creating a C program that plays the game of Tic-Tac-Toe. In Tic-Tac-Toe, players take turns picking spots on the gameboard to fill with either an X or an O. To implement this, you will need a function that reads the user's input and stores it for future use. We've provided the function extract_numbers, but we've encountered into a bug that we ran out of time to fix. Use your GDB skills to debug extract_numbers so that we can have a working Tic-Tac-Toe implementation by the end of next section!

Hint: You may find the manual pages for strtok and atoi helpful.

You can find for the code for this problem in tactactoe.c. To build this code, run make tictactoe.

Below is a buggy implementation of the extract_numbers function:

/* Function extract_numbers
*
* Arguments:   input, character pointer corresponding to null-terminated input string to extract numbers from
*              input should be in the format of AxB, where A and B are numbers corresponding to row and col, respectively
*              row and col, integer pointers that allow for accessing both the inputted row and col
* Returns:     integer, indicating if inputted move was valid
*              (row and col could be read and are both non-negative)
* Description: Extracts two numbers from STDIN based on user input.
*              Reads input from user indicating a row and column for move (in the format RowxCol)
*              Errors if both numbers are not inputted in this form or if either is negative
*/
int extract_numbers(char *input, int *row, int *col) {
   // Initialize variables
   row = 0;
   col = 0;

   // Extract the first number (row)
   char *token = strtok(input, "x");

   // Error check for incomplete string before calling atoi
   if (token == NULL)
       return -1;
   int x = atoi(token);

   // Extract the second number (column)
   token = strtok(NULL, "x");

   // Error check for incomplete string before calling atoi
   if (token == NULL)
       return -1;
   int y = atoi(token);

   // Error check to make sure both numbers are non-negative
   if (x < 0 || y < 0) {
       return -1;
   } else {
       row = x;
       col = y;
       return 0;
   }
}