Homework 6: C Introduction 1
Table of Contents
This assignment is to be done individually. You can talk to other people in the class, me, and any of the course staff (graders, lab assistants, prefects) for ideas and to gain assistance. You can get direct help debugging your code from me and any of the course staff, and you're welcome to show us your code during debugging or other conversations. The code that you write should be your own, and you shouldn’t directly show or share your code with other students (although you may discuss general debugging strategies with others). See the course syllabus for more details or just ask me if I can clarify.
1 Get started
You'll download the folder with the starter code from the link below. Like for homeworks 1 and 2, unzip the folder and move it to where you'd like: the folder for the Docker container if you're using Docker, or COURSES if you're not. Then get started in VS Code (see Homework 1 if you get stuck).
If when running tests you run into a permissions error, you can fix this by running the following code in the terminal:
chmod a+x test-e test-m
This tells the computer that all users should be permitted to execute (run)
the files test-e
and test-m
.
You can run the tests in the same way as you did for the Scheme homeworks.
2 Your tasks
2.1 Run your first program
Create a new file called hello.c
in VS Code. Then, copy and paste the
content from this linked hello.c file into that file. This program
(unsurprisingly) is supposed to print "Hello, world!" to the
screen. The top line, /* Hello World in C */
, is a comment: /*
starts
the comment and */
ends the comment. (Like in Java, you can also use
//
for comments within a function.)
Next, 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 named hello
. You should be able
to see it in files list in VS Code, and also if you type ls
in the terminal. Try running it at the command prompt:
./hello
If this worked, you should see "Hello, world!" output to the terminal.
EXERCISE 1: Change the program to print
Hello, CS251!
Run the program again (after recompiling it). When complete, you can also run
./test-m
, which will run the automated M tests.
There are three sections of tests. If all went well, the HelloTests should pass. You'll know that happened by the fact that you don't see any errors or failures for HelloTests, and the last couple lines of output should look something like:
Ran 3 tests in 0.183s FAILED (errors=2)
Your number of seconds will differ (mine was 0.183 seconds), but it
should say it ran 3 tests and only 2 of them had errors. If it says
FAILED (failures=1, errors=2) that means that your printing in
hello.c
isn't quite right.
2.2 Printing
The first non-commented 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 IO functions, such as printf
.
The documentation for most of the built-in C functions can be found in the UNIX manual ("man") pages. Take a look at the documentation for printf in particular. It 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 behavior of the function of interest. In this case, the manual page also includes several similarly-named functions such as sprintf
and fprintf
. Read through the first few paragraphs the man page for printf
, and skim through the rest so you get a sense of what these pages look like. There are examples at the end, which is often the most useful part.
printf
is similar to Python's string formatting operator, in that it
accepts a string that includes format specifiers to print integers,
floats, etc. To see more about how printf and other operations work,
create a file name printing.c
in your directory, and then copy in
the contents of this printing.c file. It contains a number of different examples of print formats. To compile and run your code, go back and look at how we did it for the hello.c
program, and change accordingly.
Here are some common C types and their printf
formatting specifications:
Format specifier | Type |
---|---|
%c | char |
%i or %d | int |
%li or %ld | long |
%f | float |
%s | string (really a char *) |
%p | pointer (e.g. int *) |
EXERCISE 2: Add code to printing.c
that subtracts the value 15 from 87 and
prints the result, together with an appropriate message. Check the
PrintingTests section of the results from running ./test-m
to see if you've got it working correctly.
2.3 User Input
You can get user input using the scanf
function (the manual page is here):
int i; scanf("%i", &i); printf("You entered: %i\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 the value of i
can be modified from within scanf
. There will be much more on pointers later.
EXERCISE 3: Write a program temperature.c
that asks the user for a temperature in Fahrenheit and prints the temperature converted to Celsius. Assume that the input is handled as a float
, instead of as an int
. The relevant formula is:
temp_c = (temp_f - 32) * 5/9
For example, here's what a sample run of temperature.c
might now look like:
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.)
Check the TemperatureTests section after running ./test-m
to see if you have the output correct.
2.4 Loops and if statements
C has basically the same syntax for if statements, for loops, while loops and do/while loops as Java. However, there is a critical and very subtle difference with if
statements that you should be aware of. C doesn't have boolean variables, exactly. It just has integers, so false is 0 and true is any non-zero value. So the following abomination is legal C code:
int x = 1; int y = 0; if (x - y) { printf("You entered two different numbers!\n"); } else { printf("You entered the same number!\n"); }
If you want to make your code more clear, you can use the library stdbool.h
as follows:
#include <stdbool.h> int main() { bool x = true; }
However, this is just syntactic sugar, which is a fancy phrase which means that we haven't changed the underlying language, we've just changed the syntax a little bit. With the above, x
is really just an int
, and true
is really just a 1
. Why does this matter? Try running the following BUGGY code and see what happens. (You can create a new file for this called buggy.c
for it.)
#include <stdio.h> int main() { int x = 3; if (x = 5) { printf("x must be 5, even though I assigned it to 3.\n"); } }
Happily, clang
does try to warn you when you do this.
EXERCISE 4: What happens if the user enters an impossible
temperature in Exercise 3? Absolute zero, which is the coldest
temperature anything can possibly be, is -459.67 Fahrenheit. Modify
temperature.c
so that if a temperature lower than that is input, it
displays the text "Invalid temperature." This test is in the E
tests. Run ./test-e
to see if you have this part correct.
3 Submitting your work
You'll submit your work on Gradescope. First, create a CollaborationsAndSources.txt
file in the same folder as your code. In that file, indicate
in what ways (if any) you collaborated with other people on this
assignment. Indicate any people you talked about the assignment with
besides me (Anna) and our prefect. Did you share strategies with
anyone else? Talk about any annoying errors and get advice? These are
fine things to do, and you should note them in the CollaborationsAndSources.txt
file. Give the names of people you talked with and some description of
your interactions. If you used any resources outside of our course
materials, that is also something to note in Collaborations.txt. If
you didn't talk with anyone or use any outside sources, please note
that explicitly in CollaborationsAndSources.txt
. Look back at the
Scheme intro 1 instructions if you want more details on the
CollaborationsAndSources.txt
file.
After making CollaborationsAndSources.txt
and finishing the
assignment, upload your files on Gradescope.
You should include all files that end in .c
.
You don't need to include the compiled files.
Note that if you submit a zip on Gradescope, you should submit a zip of the files, not a zip of the folder that contains the files. If all tests fail on Gradescope but they're working on your machine, this is likely the problem.
On Gradescope, you should see autograder output for the same tests as you ran locally. There is a very small but nonzero chance that you have coded something unexpected that causes the tests to pass on the computer you’re working on, but not on Gradescope. We will be grading this assignment based on the results of the tests on Gradescope, so you should make sure to pay attention to how the tests run there as well when you submit.
For grading, you'll earn at least an M if the following conditions are all met:
- All M tests pass
- A visual inspection of your code shows that you have not hyper-tailored your code to pass the tests. Hyper-tailoring your code would be doing things like checking for the exact input from the test, meaning you haven't written your code in a way that would work for similar inputs.
- You have a
CollaborationsAndSources.txt
with the information described above. - The work is turned in by the late deadline.
You'll earn an E if:
- All conditions above for an M are met.
- All the E tests pass.
- Your code is not significantly more complex than needed to accomplish the task.
- You have a comment before each function describing what the function does (its input/output behavior, not a play-by-play of "first checks… then makes a recursive call …").
- The homework is turned in by the regular deadline, or it is turned in by the late deadline and you elect to use a late token (by stating this in a regrade reguest after grading is complete).
If your code does not meet the criteria for an M or an E, then you'll earn a
grade of NA (Not Assessable) or SP (Some Progress) for the assignment. Not Assessable means that your submission does not
have an attempt at one or more functions in the assignment or was not turned in by the late deadline. Some Progress means
that your submission has some code (in the correct language) for all functions in the
assignment, but that the code does not pass all of the M tests, is
hyper-tailored to the tests, and/or is missing a CollaborationsAndSources.txt
file.
Good luck, ask questions, and have fun!
Assignment originally designed by Dave Musicant - thanks for sharing!