C
Search and filter
Write search and filtering with function pointers.
Search by title
To find a book by title, write find_by_title. Signature: Book *find_by_title(Library *lib, const char *title). Return type Book *; the found book's address or NULL.
Body: loop with for (int i = 0; i < lib->count; i++); check if (strcmp(lib->books[i].title, title) == 0) return &lib->books[i];. strcmp compares two strings; 0 means equal. After the loop, return NULL;. This pattern is the standard form of search functions in C; a pointer return carries both result and failure.
Filtering patterns
To filter a collection, use a predicate function: typedef int (*BookPred)(Book *);. BookPred is a function pointer taking a Book and returning int. A filter function takes this pointer and prints the matching books.
Example predicate: int is_borrowed(Book *b) { return b->borrowed; }. Inside filter loop with for and call the predicate with if (pred(&lib->books[i])). This is a real use of function pointers; the filter stays the same even when the predicate changes. This technique is C's equivalent of the strategy pattern in non-OO languages.
Exercise Add find_by_title
Add Book *find_by_title(Library *lib, const char *title) to the existing code. Body: loop with for (int i = 0; i < lib->count; i++); check if (strcmp(lib->books[i].title, title) == 0) return &lib->books[i];; after the loop return NULL;. In main add a book, call Book *found = find_by_title(&lib, "C Tutorial"); and if (found) print_book(found);.
Show example solution
#include <stdio.h>
#include <string.h>
typedef struct {
char title[64];
int year;
int borrowed;
} Book;
typedef struct {
char name[64];
int id;
} Member;
typedef struct {
Book books[10];
int count;
} Library;
void library_init(Library *lib) {
lib->count = 0;
}
void library_add(Library *lib, Book b) {
lib->books[lib->count++] = b;
}
void print_book(Book *b) {
printf("Book: %s (%d)\n", b->title, b->year);
}
int checkout(Book *b) {
if (b->borrowed) return 0;
b->borrowed = 1;
return 1;
}
int return_book(Book *b) {
if (!b->borrowed) return 0;
b->borrowed = 0;
return 1;
}
Book *find_by_title(Library *lib, const char *title) {
for (int i = 0; i < lib->count; i++) {
if (strcmp(lib->books[i].title, title) == 0) return &lib->books[i];
}
return NULL;
}
int main(void) {
Library lib;
library_init(&lib);
Book b1 = {"C Tutorial", 2024, 0};
library_add(&lib, b1);
Book *found = find_by_title(&lib, "C Tutorial");
if (found) print_book(found);
return 0;
}
Test yourself
-
Match search tools
- strcmp
- String comparison
- Book *
- Return type
- NULL
- Not found
- lib->count
- Loop bound
-
What does find_by_title return when not found?
Show answer
NULL — When not found it returns NULL; the caller checks for NULL.
-
Complete the strcmp comparison
if (____(lib->books[i].title, title) == 0) return &lib->books[i];
Show answer
if (strcmp(lib->books[i].title, title) == 0) return &lib->books[i];
Next lesson: Putting it together