| Exercise | Focus |
|---|---|
| 0. printing | printf format specifiers, arithmetic expressions, and writing a complete C program from scratch. |
| 1. printf-width | Width fields in printf and controlling minimum field widths for formatted output. |
| 2. printf-precision | Precision fields in printf and formatting integer and floating-point output. |
| 3. Coupon Discount | Building a multi-step calculation using integer arithmetic. |
| 4. Image Effect 1 | Applying conditionals and integer arithmetic to transform RGB pixel values. |
Getting Started
- Don’t know how to get started with a Volume? Refer to the instructions in Tutorial 0
- To understand how the volumes are graded, refer to How Are Volumes Graded
- To read our expectations for code in this course (which we will teach you over time), read C Standards
0. printing
Focus
printfformat specifiers, arithmetic expressions, and writing a complete C program from scratch.
Introduction
In the lecture, we went through examples of writing program output using the printf function. To print the value of a variable, we use format specifiers, such as %d for integers and %f for floating-point values.
For example:
#include <stdio.h>
int main(void) {
double a = 1.4;
int b = 5;
printf("a: %f\n", a);
printf("b: %d\n", b);
}This exercise also gives you practice with arithmetic expressions and integer division.
Your Task
student.c is empty. Write the whole program from scratch. Print each result on its own line, in this order:
1.0 + (1.0 / 3.0)as a floating-point value1.0 + (1 / 3)as a floating-point value19283745using%d19283745using%x19283745using%b
The %b conversion specifier requires the newer C library environment provided by the course WebTop. Your program should produce five lines of output.
Pay particular attention to the difference between 1 / 3 and 1.0 / 3.0, and to the last three representations of the integer. You can refer to the man pages if you want to investigate the format specifiers further.
Running
- To compile, run
make - To run, run
./printer - To test, run
make test
Intent
This exercise is intended to help you get used to writing small programs from scratch, including importing headers, defining main, and writing the required program behaviour. Later in the course, you will often modify parts of larger programs, but writing complete small programs is still a useful skill.
1. printf-width
Focus
Width fields in
printfand controlling minimum field widths for formatted output.
Introduction
In the lecture, we showed a few basic ways to print integers and floating-point values. There is a lot more that we can do with printf, so let’s explore the width modifier.
Recall that to print an integer of type int and a floating-point value of type double, we can write:
#include <stdio.h>
int main(void) {
int a = 5;
double b = 3.141;
printf("%d\n", a);
printf("%f\n", b);
}Think of d and f as conversion specifiers. To specify a minimum field width, write the width between % and the conversion specifier. For example, printf("%5d", a); uses a minimum width of 5 for an integer, while printf("%2f", b); uses a minimum width of 2 for a floating-point value.
Padding With Spaces on the Left
If a has value 123 and you write printf("%5d", a);, printf adds two spaces on the left so that the field is at least five characters wide. The width is a minimum, so a value wider than the requested width is not truncated.
By default, values are padded with spaces on the left. The left-adjustment flag can be used to pad with spaces on the right, but that is not required for this exercise.
Your Task
In student.c, define and declare a variable a with value 12345. Print two lines, each ending with a newline:
- The first line should print
awithout any other specifiers - The second line should print
awith a width of 10
Running
- To compile, run
make - To run, run
./printer - To test, run
make test
2. printf-precision
Focus
Precision fields in
printfand formatting integer and floating-point output.
Introduction
In the lecture, we showed a few basic ways to print integers and floating-point values. There is a lot more that we can do with printf, so let’s explore one of its many features.
The precision modifier tells printf how to print numbers. For integer values, it sets the minimum number of digits. For floating-point values, it sets the number of digits after the decimal point.
Recall that to print an integer of type int and a floating-point value of type double, we can write:
#include <stdio.h>
int main(void) {
int a = 5;
double b = 3.141;
printf("%d\n", a);
printf("%f\n", b);
}Think of d and f as conversion specifiers. To specify precision, write a period followed by a number between % and the conversion specifier. For example, printf("%.5d", a); uses a precision of 5 for an integer, while printf("%.2f", b); uses a precision of 2 for a floating-point value.
According to man 3 printf, precision gives the minimum number of digits for integer conversions and the number of digits after the decimal point for f conversions. Thus, printf("%.3d", 15); prints 015, while printf("%.2f", 3.141); prints 3.14.
Variable Precision
You can also store the precision in a variable. To print a floating-point value with a precision stored in prec, write:
#include <stdio.h>
int main(void) {
int prec = 5;
double pi = 3.141;
printf("%.*f\n", prec, pi);
}The * tells printf to read the precision from the argument before the value itself.
Your Task
In student.c, define and declare these two variables:
a, adoublewith value3.141b, anintwith value5
Your program should print five lines, ending with a newline:
- The value of
awithout a precision specifier - The value of
awith precision 2, using an explicitly written precision - The value of
awith precision 5, using variable precision syntax - The value of
bwithout a precision specifier - The value of
bwith precision 2
Running
- To compile, run
make - To run, run
./printer - To test, run
make test
Note
The bonus exploration in the source exercise asks you to investigate what happens when a variable precision is used with an incompatible argument. It is not part of the submission requirements.
3. Coupon Discount
Focus
Applying specifications step by step
Introduction
Let’s try writing a simple program that does some computations about coupon applications (as a follow up to the first lecture).
Your Task
Note
We’ve set up a program that reads one integer price from $0 to $1,000,000. Apply the following rules to the price:
- Apply a voucher whose min-spend is $50, which applies a discount of 20% of the price of the product, but this discount is capped at $20.
- The discount amount should be based on integer arithmetic.
- After subtracting the discount from the original price, apply 19% GST (woah!) to the discounted price using integer arithmetic.
- Print the final price.
Open student.c. Implement the required behaviour by writing the code indicated below the line.
Running
- To compile, run
make - To run, run
./coupon - To test, run
make test
Inputs are validated for you. To add test cases, create a file named [your file name here].in in test/test_cases. The file should contain an input value you want to use to test your program:
[input value here]For example, to test the program with an input price of 888, create a.in with:
888Create a matching a.out containing the expected result:
1032Only add code in the area specified
Only add code below the comment that says to add code below the line. If you somehow mess up this file, you can use the menus within the
cs1010command to reset just this exercise.
4. Image Effect 1
Focus
Just a little bit of fun with what you already know after week 1.
Introduction
Have you ever wondered how certain image effects (or “filters”) are computed?
Your Task
Here’s an interesting idea that you’re going to be a part of. We’re going to have you write a small snippet of code which happens to be the core logic for a simple image effect.
Pixels
Have you ever wondered how images are represented? You can think of an image as a rectangular grid of RGB values (red green blue). It’s actually a little more complicated than that but a good enough explanation for our purposes.
Basically, for a screen display, any colour is just a blend of some amount of Red, Green, and Blue colours. So, typically, a pixel is represented as a triplet where the values range between 0 and 255. Think of 255 as full brightness at 100%, and 0 as 0%. So something like means full brightness from all 3 colour channels, which turns out to give us white. This also means the three pixels , , and just give you the “purest” possible red, green, and blue. Any other pixel like or is just a blend of the three colours.
It turns out it’s actually really complicated IRL but essentially that’s what it boils down to.
Effect and Design
Let’s look at the before and after of this image.
Before:

After:

…maybe I shouldn’t have used the Mona Lisa as an example image…
We’re going to try to figure out the exact step-by-step process behind the pixel transformations above, and then reproduce it. Don’t worry about how to read or parse image files, we’ll do that for you. All you have to understand is what a pixel is.
You might notice that the brighter pixels get turned a blue-ish colour, and the darker ones turned black. So at least right now, the first thought might be:
“If a pixel is bright enough, we will set it to some blue RGB value. Otherwise, we will set it to black.”
For the sake of simplicity, let’s just pick some RGB values right now.
“If a pixel is bright enough, we will set it to . Otherwise, we will set it to .”
The next step is to figure out how “bright” a pixel is based on its RGB values. Intuitively, being “pure white”, should be the brightest. And being “pure black” should be the darkest. But what about other colours in between?
We’ll use one possible measure for this idea that we’ll call luminance ():
Since and the values for range from 0 to 255, this means also takes on a value within the range to .
Great! We now have a measure of “brightness” to use. So let’s try to refine our condition to be a little more precise. Our rule is now: if a pixel is 50% or brighter, then we will set it to our coloured pixel . Otherwise, set it to black.
Since the luminance ranges from 0 to 255, we could say as long as the luminance is 127 or below, then we will set the pixel to black. Otherwise, set it to .
You can now look back at the image and see how this might give us the effect we want.
Code Structure
We’ve set up a simple program for you in student.c that reads three comma separated numbers within the range 0 to 255 and treats them as the RGB values for a single pixel.
If you implement the logic correctly, the program will decide based on the luminance of the input pixel value, whether to make it a black pixel or a blue pixel, then output the resulting pixel value.
What You Should Do
Open student.c and write your code where specified to implement the rule above.
Running
- To compile, run
make pixel - To run, run
./pixel - To test, run
make test
Inputs are validated for you. To add test cases, create a file named [your file name here].in in test/test_cases. The file should contain three comma-separated RGB values:
[r value],[g value],[b value]For example, to test pixel with an input pixel of 127,50,200, create a.in with:
127,50,200Create a matching a.out containing the expected result:
0,0,0Explanation: The pixel is too dark to be turned into a blue pixel, so it’ll be set as black.
Bonus (Ungraded)
When you’re ready, you can then open up pixel_effect.h instead and write the same code you just did into the location shown in the file. You will then have a program that applies the effect to entire uncompressed 24-bit .bmp images.
Why BMP
Why
.bmp? Because other image formats are hard to parse. 😭
Opening the Included Sample Image
The exercise already includes mona-lisa.bmp, an uncompressed 24-bit BMP. In the WebTop terminal, first change to the 4-image-effect-1 exercise directory, then open the image with WebTop’s default image viewer:
open ./mona-lisa.bmpThis opens the image using feh, the image viewer installed in WebTop. Press q while the image viewer is focused to close it and return to the terminal. You can also invoke the viewer directly with feh ./mona-lisa.bmp.
Applying and Viewing the Effect
Compile the full-image program, apply the effect, and open the result:
make effect
./effect mona-lisa.bmp my-effect.bmp
open ./my-effect.bmpThe input and output filenames must be different. To use another image, place an uncompressed 24-bit BMP in the exercise directory and replace mona-lisa.bmp with its filename.
Downloading More Images
For more images to experiment with, download these files from John Burkardt’s BMP sample collection:
wget -O three-colours.bmp https://people.math.sc.edu/Burkardt/data/bmp/bmp_24.bmp
wget -O snail.bmp https://people.math.sc.edu/Burkardt/data/bmp/snail.bmpBoth are uncompressed 24-bit BMPs that work with the provided full-image program. For example:
./effect snail.bmp snail-effect.bmp
open ./snail-effect.bmpThis is ungraded, so feel free to experiment with manipulating pixels however you like. You could try creating a negative, converting the image to grayscale, or accentuating one colour more than the others.1
Footnotes
-
(Instagram filters are kind of like this) ↩