For this lab, you are welcome to get technical help from another student on how to use or install any of the tools involved. You may also get syntax help on C. You may not, however, get help on the algorithmic portion of the exercise outside of office hours or piazza questions to TAs or instructors.
This lab is broken down into several steps:Homework 1, which includes warmup 1, will be collected from your subversion repository on Wednesday, April 6th, at 11:59pm.
https://phoenixforge.cs.uchicago.edu/svn/CNET-cs152-spr-16with your own CNet ID in place of CNET. To check out the repository to your current location:
$ svn checkout https://phoenixforge.cs.uchicago.edu/svn/CNET-cs152-spr-16
This will give you a working directory that you can commit to, storing it for retrieval from any location.
Now set up your working directory. I will not give this level of directions every lab - this is just to remind you of the unix commands that accomplish these tasks. You may refer back to this lab if you forget in the future.
$ cd CNET-cs152-spr-16 $ mkdir hw1 $ svn add hw1 $ cd hw1
We expect you to use vim (for editing) and clang (for compiling) this quarter, though there are many other tools available for code editing and C compilation. These two have the virtue of working entirely from the console. Among other desirable properties, this makes it painless to work on the CS network using vim and clang from a remote computer (such as your laptop, in your room, on a freezing winter night).
Here are a few words about each of these applications.
Vim stands for "vi improved" and is an updated
(though not recently) version of the classic
editor vi. Vi (when you say this out loud, you say
both letters individually:
Vi has a modal interface, which is to say it has various modes you can be in (or not in) at any given moment. When you start vi, you are in command mode. To edit text, you need to switch to insert mode. You switch to insert mode by typing i, and you switch to command mode by typing the esc key.
You issue commands in command mode by typing a colon (:) and then one or more characters naming the command; for example, :q quits vi and :w writes the current file to disk (think of :w as "save").
At some point this week, but not during this lab period, you should go through vimtutor. This will take about 30 minutes and will give you practice with an assortment of vi tools and techniques. You can do so by opening a terminal and typing vimtutor.
In order to practice editing and compiling, let's begin with a small function that we have already written for you. Open a new file named functions.c, then copy and paste this function into the file. If the formatting is not retained, use your vi skills you just learned in vimtutor and edit the file. You can copy using the standard copy mechanism. Then paste in vi by going into insert mode (by pressing 'i') and using the standard paste mechanism. Because the mechanisms are dependent on the type of computer you are current sitting at, I am not describing the mechanisms.
To open a new file named functions.c:prompt$ vi functions.c
This code has been chosen especially to introduce you to not only the syntax and semantics of C, but also norms we will expect in this class. Take note of:
Click on this link to get the code. Then you
can place yourself in insert mode in your file (press 'i'),
copy the code from the
screen, and paste it into your file. Then press
A few comments:
Now that you have code written, you need to test it. This requires a main file. All C programs begin in main. We are going to place this main function in a different file so that we can easily swap out what code is calling this function.
We also need a way for the function calls in the main code to get to the functions we wrote in functions.c. A header file is necessary to inform the code in main.c about what the function call names are, what the input arguments are, and what the return types are.
Whenever you call functions that are in one file from another file, you need a .h file. Make a new file called functions.h. Place the code found here in the file. This shows the format of the file, but it has only one function in it. You need the prototype of each function in the file, along with a comment stating the purpose.
Now we need the main function. Make a new file named "main.c". Click on this link, then copy and paste the code into your file.
You will compile your programs using clang, a popular open-source C compiler that ships with current Macintoshes, like those we have in CSIL, and is furthermore available for free installation on other platforms.
Your program has three files - functions.h, functions.c, and main.c.
If a program has only one file, the compile line is the following:
$ clang myprogram.cThis is not the case for us, however. You have two choices - compile each part individually and combine at the end or compile in one step.
$ clang functions.c main.c
$ clang -c functions.c $ clang -c main.c $ clang functions.o main.o
If the compilation is successful, you'll see nothing at the terminal, but the compiler will have created an executable file named a.out. You can run the executable by typing ./a.out.
You can specify a different filename for the executable, other than the default name a.out, with the -o flag as follows:
$ clang -o go functions.c main.c
and then run it with ./go.
If your program includes math.h, depending on the system you're working on, you might need to include the compiler flag -lm to link in the math library. This flag appears as another option to the compile command, like so:
$ clang -lm -o go functions.c main.c
Since -lm is sometimes necessary and never harmful, you
should make a habit of compiling with it whenever math.h is
part of your program.
You can give command-line arguments to clang in standard UNIX style. We will spruce up the call to clang in this case to do two things: first, to be aggressive about warning the programmer about potential problems in the code, and second, to name the executable something other than the standard a.out. Try this command:
The option -Wall means "all warnings." You will come to appreciate these warnings; they save you a lot of time and toil.$ clang -Wall -o testprogram functions.c main.c
There is a compilation tool make that looks for a file named Makefile containing compilation instructions. You will now create a Makefile containing instructions on compiling the evidence tool in progress. Create Makefile and write the following into it:
Please note that on the second line (after the line that starts with testprogram:), the first character is a TAB: exactly one of them. This is important; the Makefile is not well-formed without it. Having created this Makefile, you can now compile the "tests" executable by simply typingtestprogram: functions.h functions.c main.c clang -Wall -o tests functions.c main.c
Try it!$ make testprogram $ ./testprogram
Dissecting the first Makefile line: The first word is the target. If you type that label into make, then it goes to that rule first. After the colon, it has a list of files. These are all of the files on which the executable depends. It looks at when those files were changed. If they were changed more recently than the target has been compiled, then it executes the compile line.
Make is a language-agnostic tool; it doesn't care if it's compiling C, Racket or anything else. It has many more capabilities than we will discuss today or even this quarter. It is a powerful assistant in software development of all stripes. The more code you write, the more you will have occasion to use and appreciate it.
Once you have compiled your code, you are ready to test it through
executing it. If you did not name it anything special, then you will
run it with:
$ ./a.out
To kill a program that is running for too long, because of an infinite loop or for any other reason, type Ctrl-c in the terminal.
Once you start executing, you may find that one of your test cases has a result that does not match the expected result. You are now ready to move on to debugging. Think of debugging as an investigation. Let's say you lost your keys. You know you had your keys this morning, and now, 8 hours later, you notice you do not have your keys. The beginning and end is not enough information. You need to figure out all the places you went in order to think about where those keys might be. Likewise, with bugs, you need more information than the beginning and the end. You need to think about what the expected result is partway through the execution of the program, and then see if it is that result there (with a print statement). You can, in essence, use a binary search of your code to find your bug. Print out intermediate results during the program, and gradually narrow down when the execution goes differently than you thought it should.
When you are done, save the file. Then add it to your svn repository. This would be a good time to commit your work!Often, you will make mistakes when you type in your code. The compiler will find many of these. Unfortunately, sometimes it is difficult to figure out what the problem is from the error messages. In order to familiarize yourself with some common error messages, you're going to intentionally introduce errors and then see what error messages result from them.
Before you start, copy your working files to new filenames so you don't ruin your working files.
$ cp main.c errormain.c $ cp functions.c errorfunctions.c
Copy and paste the following list into a file named errors.txt. For each problem, it first tells you what error to introduce into one of the files. Once you do this, compile the code again. Remember to use these files names - errormain.c and errorfunctions.c. Then copy and paste the error message into the file on the line starting with #). Then correct the code before moving to the next one.
$ svn add hw1
$ svn add functions.c functions.h main.c Makefile errors.txt
$ svn commit -m "hw1 warmup complete"