⚠️ Warning: This is not the current iteration of the course! Look here for the current offering.
Show all solutions

Topics: Pointers, Strings, Debugging

Key #

Abbreviations for common ways of engaging with the class will be highlighted:

  • Q: Question for the audience, pick one person to give an answer
  • Try it: "take a minute, talk to your neighbor, speculate about an answer"
  • Hum: "hum if you think X, or hum if you think Y"

How section works #

We release section material via the CS 300 website (where you’re reading this now) and the cs300-s24-section repository (obtain a local copy with a command like git clone git@github.com:csci0300/cs300-s24-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 :-)

Section 1: Pointers and Strings #

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. Hum: Is add_print_1 pass by value or pass by reference?

Pick someone: Why is it pass by value or pass by reference?

Explain what happens when we run the line for add_and_print1

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

Pick someone: Why is it pass by value or pass by reference?

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

Question 1: GDB Exploration #

Start by showing the program and running through what it does. Then, run it---program should segfault

Q: How would you go about figuring out where the seg fault occurs in normal practice?

Someone will say "print statements" => how would that help? This is a reasonable strategy, but then your code is littered with print statements… this is where GDB can help!

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!

#include <string.h>

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 = "I love CS300!";
    char fav_char = '!';
    dereference_and_set(&fav_char, '.');

    char *smaller_string = "";

    for (size_t i = 0; i <= strlen(the_string); i++)
    {
        smaller_string = the_string + i;
        printf("%s\n", smaller_string);
    }

    dereference_and_set(smaller_string, '!');

    return 0;
}

Intro to gdb

  • Show how to open gdb
  • When you start gdb, it's not actually running—it's in a holding pattern waiting for you to do something
  • If you just run it with r, you don't get much more output
  • You can get a better view if you do layout src and see the source code

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

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?

Question 2: 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.

Briefly explain what bitwise operators are, step through with GDB to show what they're doing We recommend writing the bitwise operators on the board/screen somewhere before section starts, then referencing them later

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

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

Great! Now the wizard can learn new spells!

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.

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.