Setup
If you haven’t already, please do the Setup for the course. Otherwise, just register for the lab using grinch
: https://grinch.caltech.edu/register and
clone the repository as explained in the setup instructions. Please use the SSH link found on the registration page and in the email sent to you, it should look something like this git@gitlab.caltech.edu:cs3-22sp/lab01-blank.git
.
Unlike in CS 2, all labs in CS 3 are solo. Similarly to CS2, we will be using the ticketing system for labs (https://qa.debuggi.ng/cs3). If you have a question, please make a ticket. If you feel you would benefit from an in-person OH session, please ask in your group chat and one of your TAs will schedule time with you.
In this lab, we will be writing some functions over C Strings. C Strings can be pretty tricky because of a few “gotchas” which we’ll explore.
Our First Function
The first function you should write is string_print
:
void string_print(char *s)
Prints the contents of s
, one character per line prefixed with the character’s index (out to two digits) and a colon.
For example, the string “Adam” would appear as:
00: A
01: d
02: a
03: m
To do this, you’ll need to learn about the printf
function; you might also find the strlen
function useful.
Both function names link to our documentation on these functions!
Task 0.
Write the string_print
function in task0.c
. Note that strings can literally be treated as arrays; so, you can use the same brackets
syntax that you would in Java.
We recommend writing this function in three stages:
- Print the characters one per line
- Add in the indices
- Fix the indices to be 0-padded to two digits
To test that your function is correct, you should compile and run your code. Then, check that the output matches the example above.
To do this, run the following commands in the labradoodle terminal (the -g is not strictly necessary, unless you are attempting to debug):
clang task0.c -o task0 -g
./task0
Memory Allocation and C Strings
The next function to write is string_reverse
. This one involves creating your own string which means we need to learn how to allocate memory in C.
Allocating Memory in C
In Java, we simply write Object o = new Object()
to allocate memory for an Object
. In C, we need to call the malloc
function and
provide the exact size of the allocation we require. This usually looks like Object *o = malloc(sizeof(Object));
. There’s a couple of notable pieces of
syntax in this line:
- There’s a
*
on the left! This indicates that we’re defining a pointer to an Object. In Java, object types are references by default; in C, we need to tell the language we want a reference explicitly with the*
. - The
malloc
function!malloc
is the way we ask our system for memory. It’s roughly equivalent to the first part of thenew
keyword that provides the memory. Be careful though! Unlike Java’snew
,malloc
DOES NOT INITIALIZE THE MEMORY. This means that, when we get it, it’s total garbage. If we want all zeroes, we have to do that manually. - We’re using
sizeof(Object)
.sizeof
is a “function” that gets replaced at compile-time with the number of bytes necessary to hold the type specified in the parentheses. Generally, when we’re allocating a pointer with \(n\) stars, the argument tosizeof
should have \(n-1\) stars.
Strings in C
In C, strings are extremely primitive. They’re literally an array of bytes. As discussed earlier, pointers and arrays are roughly equivalent. So, the type for a string in C is char *
.
Notably, pointers have no concept of “length”. So, strings are “null-terminated” meaning after the last character, there is a “null character” (written \0
) to indicate the end of the
string. A very common mistake in C is not setting the null-terminator or not allocating space for it.
Writing string_reverse
Here’s the specification for the function we want to write. For this one, we’ll walk you through it step by step.
char *string_reverse(char *s)
Returns a new string with the characters in s
in the opposite order. Does not edit the original string.
For example, the input string “Adam” would return “madA”.
Task 1a.
Given the argument char *s
, we need to allocate a new string of the right length to return. Since we’re returning a reverse of the string, it should have the same
number of characters. Using the example above as well as the strlen
function, allocate enough memory for the new string. Note that strlen
DOES NOT
return a value including the null terminator; so, you’ll have to add 1 to the result before passing it to malloc
.
Task 1b. Now, write a for loop to reverse the string and return the reversed string. Note that strings can literally be treated as arrays; so, you can use the same brackets syntax that you would in Java.
Remember, malloc
does not cleanly initialize the contents of memory for us - be sure to explicitly set the null-terminator
in the string by setting the correct index to '\0'
.
To check your work, run the commands:
clang task1.c -o task1 -g
./task1
Arrays of Strings!
Finally, we’ll implement string_blanks
which requires allocating both an array and the elements inside it.
char **string_blanks(char *s)
Returns a new array of strings where each string has a _
in place of one of the characters. Does not edit the original string.
For example, the input string “Adam” would return {"_dam", "A_am", "Ad_m", "Ada_"}
.
Recall that, in Java, if I allocate an array like so:
String[] strings = new String[10];
The only thing it does is create 10 spots for String
s. If I want to actually allocate the String
s, I need to separately make and assign them. C is no different.
To create an array of strings, we use the type char **
which means “an array of char *
’s. We’ll need to allocate the container first, and then allocate each of the individual
strings in the array individually as well. Your code for string_blanks
should have two lines that make calls to malloc
. Again, remember you can use array notation with pointers.
So, array[1][2]
would refer to the third character of the second array
element.
Task 2.
Write the string_blanks
function. Then, compile, run, and check your results using the following commands.
To do this, run the commands:
clang task2.c -o task2 -g
./task2
Getting Checked Off
Labs will be due the following Tuesday from when they are assigned, at 11:30 PST. You will need to get manually checked off for most labs, as we will not be using totally automated tests. To get checked off, make a ticket saying you are done, and we will check you off as soon as possible. Please include the link to your repo in the ticket.