CodeBlanks Logo Icon CodeBlanks

Functional logic

  • C course
  • Intermediate
  • Lesson 114/116
  • 6 min

Write business logic with function pointers and callbacks.

Counting with a filter

The third lesson adds conditional counting with a function pointer. The TaskFilter typedef defines the type of functions that test whether a task meets a condition.

You define the filter type with typedef int (*TaskFilter)(const Task *);. The is_high_priority function returns 1 if the priority is 3 or greater. The task_count_if function walks the list, tests each task with the filter, and returns the count of matches. This pattern is a fine example of callback-based abstraction; the same task_count_if can be called with different filters. The code from the previous lesson is included in the starting code.

task_count_if implementation

task_count_if takes a TaskFilter and tests each task as it walks the list. For each matching task it increments the counter.

Implementation: int count = 0; const Task *cur = list; while (cur) { if (filter(cur)) count++; cur = cur->next; } return count;. Here filter(cur) calls the filter function; if it returns true, the task is counted. This shows the power of function pointers; task_count_if does not know the filter implementation, it only calls it. The same function can be used with is_low_priority or is_named_payment. This is the same callback pattern as qsort in real libraries.

Practice Add counting with a filter

Define typedef int (*TaskFilter)(const Task *);. Write int is_high_priority(const Task *t) returning t->priority >= 3. Write int task_count_if(const Task *list, TaskFilter filter); walk and count with the filter. In main add two tasks, call task_print(g_list);, count with int high = task_count_if(g_list, is_high_priority); and print printf("yüksek: %d\n", high);.

Starter code

main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Task {
    char name[32];
    int priority;
    struct Task *next;
} Task;

Task *g_list = NULL;

Task *task_new(const char *name, int priority) {
    Task *t = malloc(sizeof(Task));
    strncpy(t->name, name, 31);
    t->name[31] = '\0';
    t->priority = priority;
    t->next = NULL;
    return t;
}

void task_push_front(Task **list, Task *t) {
    t->next = *list;
    *list = t;
}

void task_print(const Task *list) {
    const Task *cur = list;
    while (cur) {
        printf("%s: %d\n", cur->name, cur->priority);
        cur = cur->next;
    }
}

// TaskFilter türünü typedef ile tanımla
// is_high_priority fonksiyonunu yaz
// task_count_if fonksiyonunu yaz
// main'de yüksek öncelikli sayısını yazdır

int main(void) {
    task_push_front(&g_list, task_new("Ödeme", 1));
    task_push_front(&g_list, task_new("Paketle", 3));
    task_print(g_list);
    return 0;
}

Sample solution

main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Task {
    char name[32];
    int priority;
    struct Task *next;
} Task;

Task *g_list = NULL;

Task *task_new(const char *name, int priority) {
    Task *t = malloc(sizeof(Task));
    strncpy(t->name, name, 31);
    t->name[31] = '\0';
    t->priority = priority;
    t->next = NULL;
    return t;
}

void task_push_front(Task **list, Task *t) {
    t->next = *list;
    *list = t;
}

void task_print(const Task *list) {
    const Task *cur = list;
    while (cur) {
        printf("%s: %d\n", cur->name, cur->priority);
        cur = cur->next;
    }
}

typedef int (*TaskFilter)(const Task *);

int is_high_priority(const Task *t) {
    return t->priority >= 3;
}

int task_count_if(const Task *list, TaskFilter filter) {
    int count = 0;
    const Task *cur = list;
    while (cur) {
        if (filter(cur)) count++;
        cur = cur->next;
    }
    return count;
}

int main(void) {
    task_push_front(&g_list, task_new("Ödeme", 1));
    task_push_front(&g_list, task_new("Paketle", 3));
    task_print(g_list);
    int high = task_count_if(g_list, is_high_priority);
    printf("yüksek: %d\n", high);
    return 0;
}

Expected output

Paketle: 3
Ödeme: 1
yüksek: 1

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Complete the is_high_priority condition

Question
return t->priority >= ____;
Answer
return t->priority >= 3;

Explanation: t->priority >= 3 is the threshold for high priority.

2 Match the filter parts

Term Meaning
TaskFilter Filter type
is_high_priority High priority
task_count_if Conditional count
filter(cur) Callback call

3 Why does task_count_if take a function pointer?

  • So it can be called with different filters Correct answer
  • To use less memory
  • To run faster
  • To avoid compiler warnings

Explanation: The function pointer lets the same function work with different filters.

All lessons in Intermediate