Lab: Arrays and Strings

Today’s lab will give you a chance to practice using arrays and strings in C. Follow these steps to set up your repository for today’s lab work:

  1. Go to https://git.cs.grinnell.edu/csc161/arrays-strings.

  2. You may still be signed in, but if you see a Sign In button in the upper right, click it and log in with the GrinCo-AAD option below the form.

  3. On the page for the arrays-strings repository, click the Fork button in the upper right. On the next page, leave all the options set to their defaults and click the Fork Repository button.

  4. You’ll end up back on a page that looks like the original repository, but the title in the upper left should be “YOUR_USERNAME/arrays-strings” with a subtitle that says “forked from csc161/arrays-strings”.

  5. Click the Settings button in the upper right and then choose the Collaborators section.

  6. For each member of your group, type their username and click Add Collaborator. That should immediately add them to the list of collaborators. This should be the default, but make sure each collaborator has Write permission (displayed next to the button to remove a collaborator). If you can’t find a lab group member, they might not have set up their Gitea account. Fix this now before moving on.

  7. Once you’ve finished adding your lab group to the repository, click the Code button to go back to the repository’s main page. Find the HTTPS button and click it if it isn’t already selected. Copy the text that appears in the field next to the SSH and HTTPS buttons.

  8. Open a terminal and run the following commands to clone your repository. Make sure you replace COPIED_TEXT with the text you just copied:

    $ cd ~/csc161/labs
    $ git clone COPIED_TEXT
    $ cd arrays-strings
    $ code .
    

You should now see VSCode running with the arrays-strings lab directory open. Don’t forget to commit and push your changes after each part of the lab.

A. One-dimensional Arrays

Open the max-min.c file you unpacked in the previous step and read through it. Once you’ve reviewed the code we will compile it, but we’ll do that a little differently this time. We’re going to use a tool called make to compile our code for this lab. Just run this command in the terminal:

$ make max-min 

Any time you edit a source file you can run make in the terminal to recompile it. The make tool will skip unnecessary compilation steps; if you run make again without editing a source file it won’t do anything. The rules that tell make how to compile code are in a file named Makefile. We’ll spend time later in the semester learning how to create Makefiles, but for now, you can trust that it will just work for your lab.

Now that you’ve compiled the code, run the max-min program in the terminal as you normally would:

$ ./max-min

Exercises

The exercises for this part will run through a series of changes you’ll need to make to the max-min.c source file. Make sure you save the changes you make in VSCode and run make in the terminal to update the build each time.

  1. What happens if you change the LENGTH constant to 5? Make a prediction, then check your prediction by compiling and running max-min.

  2. What happens if you change the LENGTH constant to 12? Make a prediction and check it by compiling and running the code.

  3. What happens if you modify the loop that prints the array to start at a negative index? Make a prediction, then check by compiling and running.

  4. What happens if you modify the loop that prints the array to read beyond the end of the array (e.g. access index LENGTH+2)? Make a prediction, then check by compiling and running.

B. Writing and Reading Arrays of Characters

For this part of the lab, you will write a program that reads a message from the user one character at a time and then prints the characters back in reverse order. Here is an example run of a completed implementation:

$ ./reverse1
Enter a message: Don't get mad, get even.
The reversed message is: .neve teg ,dam teg t'noD

Your implementation should read one character at a time using the getchar() function, up until you read either a newline character ('\n') or the message reaches 100 characters. You should use a #define constant to set the message length limit to make your code clearer and easier to update.

Caution: the getchar function likely will not receive any characters until you hit enter. Don’t be alarmed if you need to press enter to send the input to the program. Just make sure the reversed message only includes 100 characters.

Exercises

  1. First, implement your program by reading characters into an array, then print the array backwards. Your implementation must store the characters in the order they were entered, and print them in reverse order by looping backward through the array. Please complete this implementation in the file reverse1.c. Test your implementation thoroughly before moving on.

  2. Next, implement the same program using a different approach: read the characters into an array, but then copy them to a second array that holds the characters in reverse order. Add a '\0' terminator to that second array so you can print the reversed message with a call to printf("%s\n", reversed_message). Please complete this implementation in the file reverse2.c. Test your implementation thoroughly before moving on.

C. Standard String Functions

The C standard includes many functions to help you work with strings. The exercises below will ask you to explore a few of the commonly used string functions. These exercises ask you to provide written responses, but you may find it useful to try using the functions in each exercise to better understand them.

Exercises

  1. What do the strcpy and strncpy functions do? Explain any limits/requirements for the parameters to these functions, describe what the functions return, and give at least one scenario where you would use each of them. You should start your investigation of these functions in the manpages:

    $ man strcpy
    

    I strongly encourage you to experiment with both functions once you’ve read their formal documentation. Programs that violate requirements laid out in the manpage may still work, although they rely on undefined (or unsafe) behavior.

  2. What do the strcat and strncat functions do? Explain any limits/requirements for the parameters, describe what the functions return, and give at least one scenario where you would use each of them. As before, start with the manpages and then write some code to test the functions’ behavior.

  3. What do the strcmp and strncmp functions do? Explain any limits/requirements for the parameters, describe what the functions return, and give at least one scenario where you would use each of them. Again, you can read about these functions in the manpages.

D. Two-Dimensional Arrays

C also allows us to create multi-dimensional arrays; we’ll look specifically at two-dimensional arrays, but you can add more dimensions if you have data you want to access with more than two indices.

The face.c program includes a two-dimensional array that you should print out to the terminal. Each row of the array is a line of characters to print. When you print it exactly as the array is stored, you will see the following (slightly creepy) output:

$ ./face
                   __ooooooooo__                   
              oOOOOOOOOOOOOOOOOOOOOOo              
          oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo          
       oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo       
     oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo     
   oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo   
  oOOOOOOOOOOO*  *OOOOOOOOOOOOOO*  *OOOOOOOOOOOOo  
 oOOOOOOOOOOO      OOOOOOOOOOOO      OOOOOOOOOOOOo 
 oOOOOOOOOOOOOo  oOOOOOOOOOOOOOOo  oOOOOOOOOOOOOOo 
oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo
oOOOO     OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO     OOOOo
oOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOo
 *OOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO  OOOOO* 
 *OOOOOO  *OOOOOOOOOOOOOOOOOOOOOOOOOOOOO*  OOOOOO* 
  *OOOOOO  *OOOOOOOOOOOOOOOOOOOOOOOOOOO*  OOOOOO*  
   *OOOOOOo  *OOOOOOOOOOOOOOOOOOOOOOO*  oOOOOOO*   
     *OOOOOOOo  *OOOOOOOOOOOOOOOOO*  oOOOOOOO*     
       *OOOOOOOOo  *OOOOOOOOOOO*  oOOOOOOOO*       
          *OOOOOOOOo           oOOOOOOOO*          
              *OOOOOOOOOOOOOOOOOOOOO*              
                   ""ooooooooo""                    

Exercises

  1. Go to the bottom of the main function and add code to print out the face array, just as it is shown in the example above.

  2. Now, add a second loop that prints the face upside-down.

  3. Add a third loop that prints the face transposed, so the eyes are on the right and the smile is on the left. Transposition isn’t the same as rotation, but the result will look a bit like the image was rotated 90 degrees clockwise. Optional: You can print spaces in some strategic locations to account for the fact that characters in the terminal are not square.