C Basics: Exercises

See here how to set up a development environment to do these exercises.

  • You should complete the essential exercises if you want to claim you know how to program in C.
  • If you want to go further and make sure you understand everything, you can also complete the additional exercises.

Essential Exercises

  1. Printing to the console
  2. Compilation errors
  3. Using variables
  4. Data type sizes
  5. Data types
  6. Printing a string
  7. Manipulating command line arguments
  8. Determining leap years
  9. Working with arrays
  10. Aliasing types with typedef
  11. Custom data structures with struct
  12. Enumerations with enum

Printing to the Console

Write a C program displaying a large 11x9 characters 'C' using dashes. The expected output is:

   ######
 ##      ##
#
#
#
#
#
 ##      ##
   ######

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named printf.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/01-printf

Compilation Errors

The following program is supposed to print a line on the standard output, but compilation fails due to several errors:

#include <tdio.h>

void man() {
    printf("This should work!\n");
    retur 0;
}

Correct the program to have it display the following output:

This should work!

Hint: trying to build the program will have the compiler highlight the errors.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named compilation-errors.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/02-compilation-errors

Using Variables

Write a simple program declaring two variables: int_var with type int and double_var with type double. Assign a value to each of them and print their values. The expected output is as follows:

int_var: 42
double_var: 24.000000

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named variables.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/03-variables

Data Type Sizes

Write a simple program printing the size of int variables, followed on the next line by the size of double variables, followed on a third line by the size of unsigned long long int variables. On a last line, print the value of the multiplication of these 3 sizes. The expected output (on a modern 64 bits machine) is:

4
8
8
256

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named sizes.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/04-sizes

Data Types

The following code fails to compile due to a missing variable declaration:

#include <stdio.h>

int main() {

    variable = 10;

    printf("variable is %u\n", variable);

    return 0;
}

Edit the code to have it compile and run successfully. The expected output is:

variable is 10

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named types.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/05-types

Printing a String

The following program is supposed to print hi there on the standard output and exit:

#include <stdio.h>

int main(int argc, char **argv) {
    char string[8];

    string[0] = 'h';
    string[1] = 'i';
    string[2] = ' ';
    string[3] = 't';
    string[4] = 'h';
    string[5] = 'e';
    string[6] = 'r';
    string[7] = 'e';
    string[8] = '\n';

    printf("%s\n", string);

    return 0;
}

However, when compiled and executed it prints additional garbage values:

gcc string.c -o string
./string
hi there
�Fy+V

Modify the program so that it produces the expected output:

hi there

The string should still be created in the code in a character by character basis, i.e. solutions using char string[] = "hi there" will not be accepted.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named string.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/06-string

Manipulating Command Line Arguments

Write a C program that takes 3 floating point numbers as command line parameters and displays on the standard output the value of the multiplication of these 3 numbers. Examples of execution:

./cmdline 1.0 2.0 3.0
6.000000

./cmdline 1.45 2.78 3.25
13.100750

Warning. Use the type double rather than float to hold these values in order to pass the checks.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named cmdline.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/07-cmdline

Determining Leap Years

Write a C program taking a year as command line parameter and printing out on the standard output if this year is leap or not.

To determine if a year is leap, you can use the following algorithm (taken from Wikipedia):

if (year is not divisible by 4) then (it is a common year)
else if (year is not divisible by 100) then (it is a leap year)
else if (year is not divisible by 400) then (it is a common year)
else (it is a leap year)

The output format should be as described in these examples:

./leap 2000
2000 is a leap year
./leap 2100
2100 is not a leap year

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named leap.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/08-leap

Working with Arrays

Write a program that takes up to 10 integers as command line parameters. These parameters are converted to integer types into an array of int named array. Then, the program sorts the array by increasing value and prints the result as follows:

./array 5 4 6 2 1 3 
1 2 3 4 5 6

./array 5 5 120
5 5 120

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named array.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/09-array

Aliasing Types with typedef

The program below prints the dimensions of a rectangle passed from the command line arguments:

#include <stdio.h>
#include <stdlib.h>

struct s_rectangle {
    unsigned long long int width;
    unsigned long long int length;
};

void print_rectangle(struct s_rectangle r) {
    printf("Rectangle is %llu x %llu\n", r.width, r.length);
}

int main(int argc, char **argv) {
    struct s_rectangle r;
    unsigned long long int width;
    unsigned long long int length;

    if(argc == 3) {
        width = atoll(argv[1]);
        length = atoll(argv[2]);

        r.width = width;
        r.length = length;

        print_rectangle(r);
    }

    return 0;
}

Modify this program to use typedef to alias:

  • struct s_rectangle into rectangle
  • unsigned long long int into ull

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named typedef.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/10-typedef

Custom Data Structures with struct

Consider the following structure:

struct timestamp {
    unsigned int hour;
    unsigned int minute;
    unsigned int second;
}

Using this structure, write a C program adding two timestamps and displaying the result on the standard output. The program takes 6 command line parameters corresponding to the two timestamps. The addition is realised in a function named add_timestamps that takes 2 timestamp parameters and return the sum as a timestamp. Here are some output examples:

# 5h11m44s + 12h30m3s = 17h41m47s
./timestamp 5 11 44 12 30 3
17 41 47

# 10h30m50s + 1h5m15s = 11h36m5s
./timestamp 10 30 50 1 5 15
11 36 5

# 14h12m5s + 22h5m0s = 36h17m5s
./timestamp 14 12 5 22 5 0
36 17 5

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named struct.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/11-struct

Enumerations with enum

The program below uses integer to represent days of the week, 0 corresponding to Monday, 1 to Tuesday, etc.

#include <stdio.h>

int main(int argc, char **argv) {
    int d = 2;

    printf("Today is: ");
    switch(d) {
        case 0:
            printf("Monday\n");
            break;
        case 1:
            printf("Tuesday\n");
            break;
        case 2:
            printf("Wednesday\n");
            break;
        case 3:
            printf("Thursday\n");
            break;
        case 4:
            printf("Friday\n");
            break;
        case 5:
            printf("Saturday\n");
            break;
        case 6:
            printf("Sunday\n");
            break;

        default:
            printf("Unknown day...\n");
    }
    return 0;
}

Replace the use of integers with that of an enumeration named enum day, defining constants for days: MONDAY, TUESDAY, etc.

The expected output is:

./enum
Today is: Wednesday

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named enum.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/12-enum

Additional Exercises

  1. More on arrays
  2. Computing factorials
  3. Printing a right-angled triangle
  4. Printing an isosceles triangle
  5. More on enum

More on Arrays

Write a program that takes up to 10 integers as command line parameters. These parameters are converted to integer types into an array of int named array. Then, the program iterates over the array and outputs if each number is even or odd as follows:

./array2 1 2 3 4 5 6 
1 is odd 
2 is even 
3 is odd 
4 is even 
5 is odd 
6 is even

./array2 5 5 120
5 is odd
5 is odd
120 is even

Modulo in C. The modulo operator in C is %, for example: 42 % 2 evaluates to 0 and 41 % 2 evaluates to 1.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named array2.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/13-array2

Computing Factorials

Write a C program taking an integer as command line parameter and displaying the factorial of that integer on the standard output as follows:

./factorial 10
10! = 3628800

./factorial 15
15! = 1307674368000

./factorial 1
1! = 1

We assume that the parameter value can be up to 20, the maximum number which factorial can be stored in a 64 bits unsigned integer.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named factorial.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/14-factorial

Printing a Right-Angled Triangle

Write a C program taking an integer as parameter and printing a right-angled triangle on the command line which legs size is defined by the integer parameter. Here are some examples of execution:

./triangle 2
*
**

./triangle 5
*
**
***
****
*****

./triangle 15
*
**
***
****
*****
******
*******
********
*********
**********
***********
************
*************
**************
***************

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named triangle.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/15-triangle

Printing an Isosceles Triangle

Write a C program taking an odd integer n as parameter and printing an isosceles triangle on the standard output, with the triangle's base length being defined by n. Example of execution are:

./triangle 3
*
**
*

./triangle 5
*
**
***
**
*

./triangle 15
*
**
***
****
*****
******
*******
********
*******
******
*****
****
***
**
*

When the integer parameter n is even, the program corrects it to the next odd number by simply incrementing it.

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named triangle2.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/16-triangle2

More on enum

Enumerations can be used in C in combination with bitwise operations to define flags, i.e. set of properties attached to objects, each object being able to have 0 or several properties enabled.

Consider the following program:

#include <stdio.h>

typedef enum {
    /* define FLAG1, FLAG2, FLAG3, FLAG4 */
} flags;

void print_flags(flags f) {

    if(f & FLAG1)
        printf("FLAG1 enabled\n");
    if(f & FLAG2)
        printf("FLAG2 enabled\n");
    if(f & FLAG3)
        printf("FLAG3 enabled\n");
    if(f & FLAG4)
        printf("FLAG4 enabled\n");
}

int main(int argc, char **argv) {
    flags f1 = FLAG1 | FLAG2;
    flags f2 = FLAG1 | FLAG2 | FLAG3;

    printf("f1:\n");
    print_flags(f1);

    printf("f2:\n");
    print_flags(f2);

    return 0;
}

The goal of the exercise is to write the definition of flags so that the program behaves correctly, i.e. it should produce the following output:

./enum2
f1:
FLAG1 enabled
FLAG2 enabled
f2:
FLAG1 enabled
FLAG2 enabled
FLAG3 enabled

Custom typedef values. Within a typedef definition, use = to set a particular integer value for an identifier, for example FLAG1 = 42,

Bitwise operations in C. C offers operators working on the bitwise representation of variables:

  • bitwise AND: & and OR |
  • bitwise shift, left << and right >>
  • etc. For more information see the Bitwise logic and shifts operators sections here

To check the correctness of your program, use a use a Linux distribution with check50 installed and write your solution in a file named enum2.c. In a terminal, with that file in the local directory, check with this command:

check50 -l --ansi-log olivierpierre/comp26020-problems/2024-2025/week2-c-basics/17-enum2