CS 251: Programming Languages

Fall 2017

hw6: C lab, part 1

Due: Monday, 10/02 at 22:00

This assignment is to be done individually. You can share ideas and thoughts with other people in the class, but you should code your own assignment.

1. Goals

To become familiar with some basic notions in C. To get used to using Git and GitHub.

2. Introduction

C programming should be done on Linux, as described in hw0. As a reminder, you may use x2go, VirtualBox, SSH and terminal text editing, or run your own Linux machine.

3. Getting started with Git and GitHub

Before getting started with C programming, get set up with GitHub to submit your code. Do the following:

  1. Go to the GitHub organization page for this course. (You can accept the invitation to join the organization if you have not.) You should see a repository named username-lab, where username is your username. (Similarly, replace any occurrence of username below with your own username.) Contact me straight away if the repository isn't there.
  2. Clone the repository. In your web browser, click on the repository titled username-lab. This should take you to the home page for that repository. Find the box on the page that shows you the link for your repository, and make sure "HTTP" is selected instead of "SSH". (You can use SSH if you want to figure out how to set it up on your own. HTTP is easier to configure.) Copy the URL. In your Linux desktop, open up a terminal window. Navigate to a an appropriate directory that you wish your repository to live in. Then type git clone URL where URL is the URL you copied from above. It will probably look something like this:
    git clone https://github.com/cs251-17f/username-lab.git
    
  3. Add a file to the repository. To make sure that Git and GitHub are up and running, create a file and add it to the repository as follows.

    If everything worked, you should have received a (seemingly) empty directory (probably named username-lab). Please cd into it:

    cd username-lab

    Create a credits.txt file and write some text in it (using a file editor of your choice). Then issue the following commands:

    git status
    git add credits.txt
    git status
    git commit -am "Added a credits.txt file."
    git status
    
    The first status command should show you that you have a new file that is not yet tracked by Git. The add command will add it for tracking. The second status should now show that you have a file with changes ready to be committed. The commit command will commit the changes to your local repository. The third status should show you that the commit worked.

    Of course, you may skip the git status commands.

    Note: If this is your first time using Git, you may receive a warning that your name and email address were configured automatically. To make that message go away in the future, enter in the two Git config messages that it will show you.

  4. Push changes to GitHub. The commands in the previous step were operating locally, without using the Internet. Once you have successfully added your file and committed it to the local repository, push it to GitHub by issuing the following command:
    git push
    
    This tells Git to push your changes to GitHub.

    Note: If this is your first time pushing, you might get a warning message claiming that "push.default is unset." If so, follow the recommendation it provides to "adopt the new behavior now."

    git config --global push.default simple
    
    Then try again:
    git push
    

    Note: The first time pushing a repository may require

    git push origin master
    
    instead. You should only need to add origin master the first time.
  5. Go back to GitHub in your browser. Within your repository, click on the credits.txt file to confirm that your edits are showing up there. Hopefully the above all works as expected; if not, ask for help (from me, a classmate, a CS lab assistant, or Mike Tie) before going further.

4. Getting started with C

When doing the exercise below, update credits.txt by listing anyone who helped you with the assignment (including lab assistants and classmates), and any websites, books or other sources you used for reference. Also briefly describe how you were helped. Please try to be thorough. If you didn't get any help, you could write something like "I worked alone."

  1. Compiling and running your first program

    You'll need a text editor and a C compiler to work. We've got a couple of text editors in the virtual machine; emacs, vim, gedit, JEdit, and Brackets are all there. You can also install others if you like. For the C compiler, you'll use clang, which is already installed.

    In your local Git repository directory, create a file hello.c with the following contents:

    /* A first C program. */
    
    #include <stdio.h>
    
    int main() {
       printf("Hello, world!\n");
    }
    

    Add the new file to the repository:

    git status
    git add hello.c
    git status
    git commit -am "Adding hello.c"
    git status
    

    Compile the program to a binary executable by running the following in the terminal:

    clang -o hello hello.c
    

    This command should produce a file name hello. Try running it.

    $ ./hello
    Hello, world!
    
    The dollar sign ($) above represents the shell prompt. It should not be typed in. This is a (common) typographical convention to help distinguish between what to type in and the program output.

    EXERCISE: Change the program to print "Hello, <your name>!" instead. You will have to recompile the program before running it again. When complete, add and commit your changes with Git, and then push your changes to GitHub. Verify that you can see your updates on the GitHub website.

  2. Printing

    The first non-commented, non-blank line of hello.c is: #include <stdio.h>. This directs the C compiler (or technically, a subprocess called the C preprocessor) to include a header file named stdio.h that lists the signatures of standard input and output functions, such as printf.

    In a terminal window, type man 3 printf. All of the functions in the standard C library are documented in the system manual. (The 3 is because there's also a bash command named printf, so you have to specify which manual to use.) The man page tells you which header file to include to get access to that function (in this case, stdio.h), as well as documenting the interface and behaviour of the function. In this case, the man page also includes several similarly-named functions such as sprintf and fprintf. Read through the man page for printf.

    The printf function is similar to Python's string formatting operator in that it accepts a string that includes format specifiers to print integers, floats, etc. Download the file printing.c, which contains a number of different examples of print formats.

    Here are common C types and their printf formatting specifications:

    Format specifier Type
    %c char
    %i or %d int
    %li or %ld long
    %f float or double
    %s string (really a char *)
    %p pointer (e.g. int *)
    There is nothing to turn in.
  3. User Input

    You can get user input using the scanf function (see man scanf).

    int i;
    scanf("%d", &i);
    printf("You entered: %d\n", i);
    

    The first argument to scanf is a string containing formatting specification(s) for the type of input expected. In this case we expect an int.

    The second argument should look pretty weird to you. How is scanf able to modify the value of i? What's that ampersand (&) symbol? The answer is that we're actually passing a pointer to i's location, not i itself, so that the value of i can be modified from within scanf. We will discuss much more about pointers soon.

    EXERCISE: Write a program temperature.c that asks the user for a temperature in Fahrenheit and prints the temperature converted to Celsius. Recall that $x$ degrees Fahrenheit is $5(x-32)/9$ degrees Celsius. For example:

    What is the temperature in degrees Fahrenheit? 42.5
    42.500000 degrees Fahrenheit is 5.833333 degrees Celsius.
    

    (If you're interested: there are variants on the formatting specifiers that limit the number of zeroes. Read up on that further if you like.)

    Add, commit, and push to GitHub.

  4. Control structures

    C has basically the same syntax for if statements for branching and for, while, (and do/while) for looping as Java. However, there are a couple of differences you should be aware of:

    • In older versions of C, you might run into problems if you declare a for loop's index variable within the loop header.
      /* But may cause you trouble. */
      for (int i = 0; i < 10; i++) {
         ...
      }
      
      It's safe to put the declaration earlier:
      int i;
      for (i = 0; i < 10; i++) {
         ...
      }
      
      However, you should be using an up-to-date C compiler, so this should not be a problem. In fact, you should treat this error as an indication that your C compiler is too old. Talk to me if this happens.
    • C doesn't have a true boolean type. C only has integers, and treats 0 as false and everything else as true. (This is similar to Scheme's #f, except that C is perfectly happy doing arithmetic on 0. So (1 + 1 == 2) + (2 + 2 == 2 * 2) is 2 in C, but (+ (eq? (+ 1 1) 2) (eq? (+ 2 2) (* 2 2))) is an error in Scheme.) For example, the following is legal C code (see subtract.c for a full listing):
      int x, y;
      printf("Enter two integers separated by a space: ");
      scanf("%i %i", &x, &y);
      if (x - y) {
         printf("You entered two different numbers!\n");
      } else {
         printf("You entered the same number!\n");
      }
      

      To be more precise, there is actually a type _Bool built in. Variables of type _Bool are only allowed to have the values 0 or 1. (Assigning a value other than 0 or 1 into a _Bool variable results in the variable having value 1; see boolean.c). If you #include <stdbool.h> you'll get the names bool, true, and false, which are aliases for _Bool, 1, and 0, respectively. Use stdbool.h and the aliases to express Booleans, please.

    EXERCISE: What happens if you enter something other than a number when prompted for the temperature for your answer to Exercise 3? Read the "RETURN VALUE" section of man 3 scanf. Modify temperature.c to obtain the return value from scanf, and check it to see if something went wrong. In the event that scanf fails, your program should exit with an appropriate error message. Add, commit, and push to GitHub when complete.

    (Note that the scanf man page gets fairly technical regarding EOF, errno, and a variety of other things. You are welcome to learn about these details, though all I intend you to do for purposes of this exercise is to read the return value from scanf and use it appropraitely.

5. Submission

You have now pushed a number of commits to GitHub. You will continue to push changes to the same repository for the next assignment. As such, the grader and I need to know which commit is the one that we should use for grading. This is handled well in Git with tags.

First, make sure your final submission (including credits.txt) is ready.

git commit -am "All my changes are committed, I may have already done this"
git push

Second, tag the last commit and push the tag to GitHub (a vanilla git push does not push tags).

git tag hw6
git push --tags

Look on GitHub after the push, and click where it says "X commits" (where X is a number). That will show you the commit history. If you click on your most recent commit, you should be able to see the tag listed there.

You cannot undo tagging, and reusing the same tag for a different commit is generally a really bad idea. As such, you should wait to tag until you are sure you have committed the version you want us to grade.

Here's a long tangent. Note that GitHub sort of displays the tags wrong: even though in Git a commit is associated with only a single tag, GitHub will show you that same tag if you click on all commits that precede it. (Note that this is making a distinction between Git, the command-line tool, and GitHub, the webserver.) GitHub is trying to be helpful by showing you all commits that contribute to a release, as that's how tags are often used, but GitHub is ultimately doing this wrong. If you want to see your tags at the command prompt, you can use:

git log --tags --decorate=full

Written mostly by Laura Effinger-Dean, with help from Kochan's Programming in C and Java labs written by Dave Musicant and Andy Exley. Some modifications by Dave Musicant, David Liben-Nowell, and Jed Yang.

Start early, have fun, and discuss questions on Moodle.