C Function Exercises

Thirteen problems, from beginner to advanced, where you write your own functions. In most of them the main function that reads input and prints the result is already written, so all you write is the body of the requested function. Press "Check" to run your code with real gcc on several inputs and see whether the output is correct.

How to use these problems
  1. Read the problem and the sample run, then write your code in the box
  2. Press "▶ Run" to try it with your own input
  3. Press "✔ Check" to test the output against several prepared inputs
  4. Stuck? Open "Hint". Solved it? Compare with "Solution & explanation"
Checking rules
  • Print output exactly as in the sample run. Do not print input prompts such as "Enter a number"
  • Trailing spaces at line ends and trailing blank lines are ignored
  • Your code is saved automatically in this browser

Note: Run and Check send your code to Wandbox, a free external compiler service, and run it with gcc.

13 problems (Beginner 4 · Intermediate 5 · Advanced 4)

Functions (13 problems)

F01 Beginner

Problem 1. Maximum of three numbers

Write a function int max3(int a, int b, int c) that takes three integers and returns the largest of them. The main function that reads the input and prints the result is provided. The output is "Max: value".
Sample run (input is underlined)
3 9 5 Max: 9
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
Store a in a variable m, then compare with b and then c: "if it is larger than m, replace m". Finally, return m; sends the value back to the caller.
#include <stdio.h>

int max3(int a, int b, int c) {
    int m = a;
    if (b > m) m = b;
    if (c > m) m = c;
    return m;
}

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    printf("Max: %d\n", max3(a, b, c));
    return 0;
}
Explanation: The result of a function is the value returned with return; it takes the place of max3(a, b, c) in the caller. Calling printf inside the function does not make a return value. If you start the maximum at 0, the function returns 0 when all the numbers are negative (the 4th test).
F02 Beginner

Problem 2. Show seconds as hours, minutes and seconds (void function)

Write a function void print_time(int sec) that takes a number of seconds and prints it on one line in the form "Hh Mm Ss" (0 ≤ sec ≤ 1000000). It returns no value (void). The main function is provided.
Sample run (input is underlined)
3661 1h 1m 1s
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
One hour is 3600 seconds and one minute is 60 seconds. Hours are sec / 3600, minutes are sec % 3600 / 60, and seconds are sec % 60. The printing is also done inside the function.
#include <stdio.h>

void print_time(int sec) {
    int h = sec / 3600;
    int m = sec % 3600 / 60;
    int s = sec % 60;
    printf("%dh %dm %ds\n", h, m, s);
}

int main(void) {
    int sec;
    scanf("%d", &sec);
    print_time(sec);
    return 0;
}
Explanation: A function whose return type is void "returns no value and just does a job (here, printing)". You do not need to write return; when execution reaches the end of the function, it goes back to the caller. If you compute minutes as sec / 60, you get the total minutes including the hours (61 minutes for 3661 seconds).
F03 Beginner

Problem 3. Leap year function

Write a function int is_leap(int year) that returns 1 if the year is a leap year and 0 otherwise (1 ≤ year ≤ 9999). A leap year is "a year divisible by 4, except years divisible by 100, but years divisible by 400 are leap years". The main function is provided.
Sample run (input is underlined)
2024 2024 is a leap year
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
As a single expression the condition is (year % 4 == 0 && year % 100 != 0) || year % 400 == 0. In C, the result of a comparison or logical operation is 1 (true) or 0 (false), so you can return this expression directly.
#include <stdio.h>

int is_leap(int year) {
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

int main(void) {
    int year;
    scanf("%d", &year);
    if (is_leap(year)) {
        printf("%d is a leap year\n", year);
    } else {
        printf("%d is not a leap year\n", year);
    }
    return 0;
}
Explanation: If you write a predicate function named is_xxx that returns 1 for true and 0 for false, code like if (is_leap(year)) reads like a sentence. Checking only "divisible by 4 means leap year" gets 1900 wrong.
F04 Beginner

Problem 4. Convert Celsius to Fahrenheit (double return value)

Write a function double c_to_f(double c) that takes a temperature c in Celsius and returns it in Fahrenheit (c × 9 ÷ 5 + 32). The main function is provided and prints the results to one decimal place.
Sample run (input is underlined)
36.5 36.5 C = 97.7 F
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
The return type is double, so you can return the result of the calculation directly, as in return c * 9.0 / 5.0 + 32.0;.
#include <stdio.h>

double c_to_f(double c) {
    return c * 9.0 / 5.0 + 32.0;
}

int main(void) {
    double c;
    scanf("%lf", &c);
    printf("%.1f C = %.1f F\n", c, c_to_f(c));
    return 0;
}
Explanation: c * 9 / 5 is computed correctly because c is a double, but if you write 9 / 5 * c, 9 / 5 is evaluated first as integer division and becomes 1, so the result is off. Also note that if the return type is int, the fractional part is cut off.
F05 Intermediate

Problem 5. Read a number backwards (pass by value)

Write a function int reverse_num(int n) that takes an integer n (0 ≤ n ≤ 99999999) and returns the number with its digits in reverse order (e.g. 1230 → 321). The main function is provided and prints the original n after calling the function.
Sample run (input is underlined)
1234 1234 reversed is 4321
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
Start the result r at 0 and repeat "r = r * 10 + n % 10; → n /= 10;" until n becomes 0. It is fine to modify n inside the function.
#include <stdio.h>

int reverse_num(int n) {
    int r = 0;
    while (n > 0) {
        r = r * 10 + n % 10;
        n /= 10;
    }
    return r;
}

int main(void) {
    int n;
    scanf("%d", &n);
    int r = reverse_num(n);
    printf("%d reversed is %d\n", n, r);
    return 0;
}
Explanation: C passes arguments by value. The n the function receives is a copy of the caller's n, so even if the function counts it down to 0, the n in main does not change and the original number can still be printed. Conversely, a function cannot report a result to the caller by modifying its parameter, so the result is returned with return.
F06 Intermediate

Problem 6. Sum and maximum of an array

Write a function int sum_array(const int a[], int n) that takes an int array with n elements and returns the sum, and a function int max_array(const int a[], int n) that returns the maximum. The main function is provided: it first reads n (1 ≤ n ≤ 100), then n integers (absolute value at most 10000), and prints the sum, the maximum and the average (to two decimal places).
Sample run (input is underlined)
5 3 8 -2 7 4 Sum: 20 Max: 8 Average: 4.00
Your code
"Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
Write an array parameter like const int a[] and receive the number of elements in a separate parameter n. For the maximum, treat a[0] as the tentative maximum and compare it with a[1] onward.
#include <stdio.h>

int sum_array(const int a[], int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += a[i];
    }
    return sum;
}

int max_array(const int a[], int n) {
    int max = a[0];
    for (int i = 1; i < n; i++) {
        if (a[i] > max) max = a[i];
    }
    return max;
}

int main(void) {
    int a[100];
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    int sum = sum_array(a, n);
    printf("Sum: %d\n", sum);
    printf("Max: %d\n", max_array(a, n));
    printf("Average: %.2f\n", (double)sum / n);
    return 0;
}
Explanation: Inside a function the size of the array is unknown, so the convention is to pass the number of elements along with it (sizeof(a) inside the function is not the size of the whole array). Adding const says "this function does not modify the array". If you start the maximum at 0, you get it wrong when all the numbers are negative (the 3rd test).
F07 Intermediate

Problem 7. Reverse an array

Write a function void reverse_array(int a[], int n) that reverses the order of an int array with n elements in place. The main function is provided: it reads n (1 ≤ n ≤ 100) and n integers, calls the function, and prints the array separated by spaces.
Sample run (input is underlined)
5 1 2 3 4 5 5 4 3 2 1
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
Swap the front element a[i] with the back element a[n - 1 - i], repeating up to the middle (i < n / 2). Use a temporary variable tmp for the swap.
#include <stdio.h>

void reverse_array(int a[], int n) {
    for (int i = 0; i < n / 2; i++) {
        int tmp = a[i];
        a[i] = a[n - 1 - i];
        a[n - 1 - i] = tmp;
    }
}

int main(void) {
    int a[100];
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    reverse_array(a, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}
Explanation: Ordinary arguments such as an int are passed as copies, but when you pass an array, what is actually passed is the location (address) of its first element, so changing a[i] inside the function changes the array in main. If the loop runs all the way to i < n, the elements already swapped are swapped again and end up back where they started.
F08 Intermediate

Problem 8. Perfect numbers (prototype declaration)

For a positive integer n (1 ≤ n ≤ 10000), write a function int sum_divisors(int n) that returns the sum of the divisors of n excluding n itself. In this problem the function definition goes after main, so a prototype declaration is placed at the top. The main function is provided: it prints that n is a perfect number if the sum of divisors equals n, an abundant number if it is larger than n, and a deficient number if it is smaller.
Sample run (input is underlined)
28 Sum of divisors: 28 28 is a perfect number
Your code
"Run" executes your code with the input above. "Check" tests it against 6 prepared inputs.
For each i from 1 to n / 2, add it if n % i == 0 (divisors other than n itself are never larger than n/2). When n = 1 the loop never runs and the sum is 0.
#include <stdio.h>

int sum_divisors(int n);   // prototype declaration

int main(void) {
    int n;
    scanf("%d", &n);
    int s = sum_divisors(n);
    printf("Sum of divisors: %d\n", s);
    if (s == n) {
        printf("%d is a perfect number\n", n);
    } else if (s > n) {
        printf("%d is an abundant number\n", n);
    } else {
        printf("%d is a deficient number\n", n);
    }
    return 0;
}

int sum_divisors(int n) {
    int sum = 0;
    for (int i = 1; i <= n / 2; i++) {
        if (n % i == 0) sum += i;
    }
    return sum;
}
Explanation: A C compiler reads the source from top to bottom, so when a function is defined after the place where it is used, you need a prototype declaration that tells the compiler its return type, name and parameter types in advance. If you delete the declaration, it is an error under C99 and later standards, and depending on the compiler you get an error or a warning. Do not forget the ; at the end of the declaration.
F09 Intermediate

Problem 9. Return a grade from a score (char return value)

Write a function char grade(int score) that takes a score (0–100) and returns a grade letter: A for 90 or more, B for 80 or more, C for 70 or more, D for 60 or more, and F below that. The main function is provided: it reads the number of students n (1 ≤ n ≤ 50) and their n scores, and prints "score pts: grade" for each student on its own line.
Sample run (input is underlined)
3 95 72 58 95 pts: A 72 pts: C 58 pts: F
Your code
"Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
Check from the highest threshold down, as in if (score >= 90) return 'A';, and return as soon as one matches. A character is written in single quotes, like 'A'.
#include <stdio.h>

char grade(int score) {
    if (score >= 90) return 'A';
    if (score >= 80) return 'B';
    if (score >= 70) return 'C';
    if (score >= 60) return 'D';
    return 'F';
}

int main(void) {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int score;
        scanf("%d", &score);
        printf("%d pts: %c\n", score, grade(score));
    }
    return 0;
}
Explanation: Executing return leaves the function immediately, so the later checks are not performed even without else. "A" (double quotes) is a string, so it cannot be a char return value. The tests check the boundaries of exactly 90, 80, 70 and 60 points.
F10 Advanced

Problem 10. Was the maximum updated? (static variable)

Write a function int is_new_max(int x) that receives an integer x on each call and returns 1 if x is larger than every value passed so far (or if this is the first call), and 0 otherwise. Remember the maximum so far in a static variable inside the function (do not use a global variable). The main function is provided: it passes n integers (1 ≤ n ≤ 50) to the function in order and prints "value: new max" or "value: -" on each line.
Sample run (input is underlined)
5 3 1 4 1 5 3: new max 1: - 4: new max 1: - 5: new max
Your code
"Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
Put two variables, static int max; and static int first = 1;, inside the function. A static variable keeps its value after the function returns, and it is initialized only once, when the program starts. If first is 1, treat the call as "the first one".
#include <stdio.h>

int is_new_max(int x) {
    static int first = 1;
    static int max;

    if (first || x > max) {
        first = 0;
        max = x;
        return 1;
    }
    return 0;
}

int main(void) {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        if (is_new_max(x)) {
            printf("%d: new max\n", x);
        } else {
            printf("%d: -\n", x);
        }
    }
    return 0;
}
Explanation: An ordinary local variable without static is created afresh on every call, so it cannot remember the previous maximum. Also, if you start the maximum at 0, the first value is not reported as "new max" when all the numbers are negative (the 2nd test). That is why a separate static variable keeps track of whether this is the first call. A static variable is visible only inside its function, so it is safer than a global variable.
F11 Advanced

Problem 11. Bank account deposits and withdrawals (global variable)

Using a global variable balance (initial value 0) for the account balance, write a function void deposit(int amount) that deposits money and a function int withdraw(int amount) that withdraws money. withdraw reduces the balance and returns 1 if the balance is sufficient; otherwise it returns 0 without changing the balance. The main function is provided: it reads the number of operations n (1 ≤ n ≤ 20) and n lines of "d amount" (deposit) or "w amount" (withdrawal) (amounts are 1–100000).
Sample run (input is underlined)
3 d 1000 w 300 w 800 Deposit 1000: balance 1000 Withdraw 300: balance 700 Withdraw 800: insufficient funds (balance 700) Final balance: 700
Your code
"Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
A global variable is declared outside any function, so every function can read and write it directly, as in balance += amount;. In withdraw, handle the failure case first with if (amount > balance) return 0;.
#include <stdio.h>

int balance = 0;   // balance (global variable)

void deposit(int amount) {
    balance += amount;
}

int withdraw(int amount) {
    if (amount > balance) {
        return 0;
    }
    balance -= amount;
    return 1;
}

int main(void) {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        char cmd;
        int amount;
        scanf(" %c %d", &cmd, &amount);
        if (cmd == 'd') {
            deposit(amount);
            printf("Deposit %d: balance %d\n", amount, balance);
        } else if (withdraw(amount)) {
            printf("Withdraw %d: balance %d\n", amount, balance);
        } else {
            printf("Withdraw %d: insufficient funds (balance %d)\n", amount, balance);
        }
    }
    printf("Final balance: %d\n", balance);
    return 0;
}
Explanation: If you write int balance = 0; inside a function, a new local variable with the same name is created and the global variable does not change (name shadowing). Withdrawing exactly the balance (the 2nd operation, w 500) must succeed, so the condition is amount > balance. Global variables are convenient because they can be changed from anywhere, but that also makes it hard to track where they changed, so use them sparingly.
F12 Advanced

Problem 12. Day of the year (combining functions)

Write a function int days_in_month(int y, int m) that takes a year y and a month m (1–12) and returns the number of days in that month, and a function int day_of_year(int y, int m, int d) that takes a year, month and day and returns which day of the year it is, counting January 1 as day 1. The leap year function is_leap and the main function are provided. The input is always a valid date (1 ≤ y ≤ 9999).
Sample run (input is underlined)
2024 3 1 Days in 2024/3: 31 2024/3/1 is day 61
Your code
"Run" executes your code with the input above. "Check" tests it against 7 prepared inputs.
Keep the days of each month in an array {31, 28, 31, 30, ...} and return 29 for February in a leap year. day_of_year is "the total days of months 1 through m−1 + d", so you can build it by calling days_in_month repeatedly.
#include <stdio.h>

int is_leap(int y) {
    return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}

int days_in_month(int y, int m) {
    const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (m == 2 && is_leap(y)) {
        return 29;
    }
    return days[m - 1];
}

int day_of_year(int y, int m, int d) {
    int total = d;
    for (int i = 1; i < m; i++) {
        total += days_in_month(y, i);
    }
    return total;
}

int main(void) {
    int y, m, d;
    scanf("%d %d %d", &y, &m, &d);
    printf("Days in %d/%d: %d\n", y, m, days_in_month(y, m));
    printf("%d/%d/%d is day %d\n", y, m, d, day_of_year(y, m, d));
    return 0;
}
Explanation: Writing small functions and calling them from other functions lets you keep the leap year handling in one place. Array indices start at 0, so the number of days in month m is days[m - 1]. If the loop runs to i <= m, it also adds the days of the month itself.
F13 Advanced

Problem 13. Sort an array in ascending order

Write a function void sort_array(int a[], int n) that sorts an int array with n elements in ascending order. Any sorting method is fine (bubble sort, selection sort, etc.). The function print_array that prints the array and the main function are provided: main reads n (1 ≤ n ≤ 100) and n integers, and prints the array before and after sorting.
Sample run (input is underlined)
6 5 2 9 1 5 6 Before: 5 2 9 1 5 6 After: 1 2 5 5 6 9
Your code
"Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
For bubble sort, inside an outer loop with i from 0 to n−2, run j from 0 to n−2−i and swap neighbours if a[j] > a[j + 1]. Each pass settles the largest remaining value at the right end.
#include <stdio.h>

void print_array(const char label[], const int a[], int n) {
    printf("%s:", label);
    for (int i = 0; i < n; i++) {
        printf(" %d", a[i]);
    }
    printf("\n");
}

void sort_array(int a[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (a[j] > a[j + 1]) {
                int tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;
            }
        }
    }
}

int main(void) {
    int a[100];
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    print_array("Before", a, n);
    sort_array(a, n);
    print_array("After", a, n);
    return 0;
}
Explanation: Changes made to an array inside a function are visible to the caller, so you can write a "sorting" function with no return value (void). If the inner loop runs to j < n, a[j + 1] reads outside the array (a[n]), so use j < n - 1 - i.

Review these lessons

← Back to all practice problems