Fonksiyonel mantık
- C kursu
- Orta seviye
- Ders 114/116
- 6 dk
Fonksiyon işaretçileri ve callback'lerle iş mantığı yazarsın.
Filtre ile sayma
Üçüncü ders, fonksiyon işaretçisi ile koşullu sayma ekler. TaskFilter typedef'i, bir görevin bir koşulu sağlayıp sağlamadığını sınayan fonksiyonların türünü tanımlar.
typedef int (*TaskFilter)(const Task *); ile filtre türünü tanımlarsın. is_high_priority fonksiyonu, öncelik 3 veya daha büyükse 1 döndürür. task_count_if fonksiyonu, listeyi gezer ve filtre ile her görevi sınar; koşulu sağlayanların sayısını döndürür. Bu desen, callback tabanlı soyutlamanın güzel bir örneğidir; aynı task_count_if fonksiyonu farklı filtrelerle çağrılabilir. Önceki dersin kodu bu dersin başlangıç koduna dahildir.
task_count_if uygulaması
task_count_if, bir TaskFilter alır ve listeyi gezerken her görevi bu filtre ile sınar. Koşulu sağlayan her görev için sayacı artırır.
Uygulama: int count = 0; const Task *cur = list; while (cur) { if (filter(cur)) count++; cur = cur->next; } return count;. Burada filter(cur), filtre fonksiyonunu çağırır; doğru dönerse sayar. Bu, fonksiyon işaretçisinin gücünü gösterir; task_count_if fonksiyonu filtre uygulamasını bilmez, yalnızca çağırır. Aynı fonksiyon, is_low_priority veya is_named_ödemeli gibi başka filtrelerle de kullanılabilir. Bu, gerçek kütüphanelerdeki qsort callback deseninin aynısıdır.
Uygulama Filtre ile sayma ekle
typedef int (*TaskFilter)(const Task *); tanımla. int is_high_priority(const Task *t) yaz; t->priority >= 3 döndür. int task_count_if(const Task *list, TaskFilter filter) yaz; listede dolaş, filtre ile say. main içinde iki görev ekle, task_print(g_list); çağır, int high = task_count_if(g_list, is_high_priority); ile say ve printf("yüksek: %d\n", high); yazdır.
Başlangıç kodu
#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;
}Örnek çözüm
#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;
}Beklenen çıktı
Paketle: 3 Ödeme: 1 yüksek: 1
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 is_high_priority koşulunu tamamla
return t->priority >= ____;
return t->priority >= 3;
Açıklama: t->priority >= 3 yüksek öncelik için eşiktir.
2 Filtre parçalarını eşle
| Kavram | Anlamı |
|---|---|
TaskFilter |
Filtre türü |
is_high_priority |
Yüksek öncelik |
task_count_if |
Koşullu sayma |
filter(cur) |
Callback çağrı |
3 task_count_if neden fonksiyon işaretçisi alır?
- Farklı filtrelerle çağrılabilsin diye Doğru cevap
- Daha az bellek kullansın diye
- Daha hızlı çalışsın diye
- Derleyici uyarısı vermesin diye
Açıklama: Fonksiyon işaretçisi sayesinde aynı fonksiyon farklı filtrelerle kullanılır.