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-f25-section repository (obtain a local copy with a command like git clone git@github.com:csci0300/cs300-f25-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 best 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, this is a great 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_and_print1 pass by value or pass by reference?

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

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

Question 1: Practice building and debugging programs #

Here’s a program that does some operations and pointers and uses strings. It also has a bug! In this part, we’ll start by getting acquainted with how to build and run the program. Then, we’ll learn more about C by exploring what this program does, and how

Running the program #

To run the program, do the following:

  1. Open up a terminal in your container environment, and cd to your container’s home folder (cd ~)

  2. Clone the section repository with git clone:

    $ git clone git@github.com:csci0300/cs300-f25-section
    
  3. If you use VSCode, open a VSCode window and attach it to the container. Then, open the sec1 folder in VSCode with File > Open Folder.

  4. In your container terminal (in VSCode or otherwise), cd to the sec1 directory and run make. This runs the compiler!

  5. Then, run your program with ./question1

Debugging the program #

Oh no, this program has a bug! How should we go about solving it??

We could make some guesses by staring at the code, but let’s learn a more systematic way that we’ll help you in your projects: we can figure out where the bug is using the GNU debugger (GDB), which is a super-helpful tool to help you reason about programs!

void dereference_and_set(char *ptr, char to_set)
{
    *ptr = to_set;
}

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 the_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;
   }
}

Creative Commons Licence This work is licensed under a Creative Commons Attribution 4.0 International License.