Skip to content

emonislive/c-stl-library

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C STL Library - Complete Reference Guide

Table of Contents

• Container Types
• Vector Operations
• Unordered Map Operations
• Stack Operations
• Queue Operations
• Set Operations
• Priority Queue Operations
• Deque Operations
• Linked List Operations
• Sorting Algorithms
• Searching Algorithms
• Utility Algorithms
• String Utilities
• Random Utilities
• Timer Utilities
• Math Utilities
• Memory Utilities
• Comparator Helpers

Container Types

// Vector - Dynamic array
vector v;
vector_init(&v, sizeof(int));

// Unordered Map - Key-value store
unordered_map m;
map_init(&m);

// Stack - LIFO container
stack s;
stack_init(&s, sizeof(int));

// Queue - FIFO container
queue q;
queue_init(&q, sizeof(int));

// Set - Unique element collection
set s;
set_init(&s, sizeof(int), compare_int);

// Priority Queue - Max heap
priority_queue pq;
priority_queue_init(&pq, sizeof(int), compare_int);

// Deque - Double-ended queue
deque dq;
deque_init(&dq, sizeof(int));

// Linked List - Doubly linked list
list l;
list_init(&l, sizeof(int));

// Pair - Key-value pair
pair p = make_pair(&key, &value);

Vector Operations

// Initialization
vector v;
vector_init(&v, sizeof(int));

// Adding elements
int value = 42;
vector_push_back(&v, &value);

// Accessing elements
int* elem = (int*)vector_get(&v, index);
int* elem_safe = (int*)vector_at(&v, index); // Bounds-checked

// Front and back
int* first = (int*)vector_front(&v);
int* last = (int*)vector_back(&v);

// Insertion and deletion
vector_insert(&v, index, &new_value);
vector_erase(&v, index);
vector_pop_back(&v);

// Capacity management
vector_reserve(&v, new_capacity);
vector_resize(&v, new_size, &default_value);
vector_shrink_to_fit(&v);

// Information
size_t size = vector_size(&v);
size_t capacity = vector_capacity(&v);
bool empty = vector_empty(&v);

// Cleanup
vector_clear(&v);
vector_free(&v);

Unordered Map Operations

// Initialization
unordered_map m;
map_init(&m);
map_init_with_capacity(&m, 64);

// Insertion
int value = 100;
map_insert(&m, "key1", &value, sizeof(int));

// Access
int* retrieved = (int*)map_get(&m, "key1");

// Operations
bool exists = map_contains(&m, "key1");
bool removed = map_erase(&m, "key1");
size_t map_size = map_size(&m);
bool is_empty = map_empty(&m);

// Cleanup
map_clear(&m);
map_free(&m);

Stack Operations

// Initialization
stack s;
stack_init(&s, sizeof(int));

// Push and pop
int value = 10;
stack_push(&s, &value);
stack_pop(&s);

// Access top
int* top = (int*)stack_top(&s);

// Information
size_t stack_size = stack_size(&s);
bool stack_empty = stack_empty(&s);

// Management
stack_clear(&s);
stack_free(&s);

Queue Operations

// Initialization
queue q;
queue_init(&q, sizeof(int));

// Enqueue and dequeue
int value = 20;
queue_enqueue(&q, &value);
queue_dequeue(&q);

// Access
int* front = (int*)queue_front(&q);
int* back = (int*)queue_back(&q);

// Information
size_t queue_size = queue_size(&q);
bool queue_empty = queue_empty(&q);

// Management
queue_clear(&q);
queue_free(&q);

Set Operations

// Initialization (requires comparator)
set s;
set_init(&s, sizeof(int), compare_int);

// Insertion and lookup
int value = 30;
set_insert(&s, &value);
bool contains = set_contains(&s, &value);

// Removal
bool removed = set_erase(&s, &value);

// Information
size_t set_size = set_size(&s);
bool set_empty = set_empty(&s);

// Cleanup
set_clear(&s);
set_free(&s);

Priority Queue Operations

// Initialization (requires comparator)
priority_queue pq;
priority_queue_init(&pq, sizeof(int), compare_int);

// Push and pop
int values[] = {5, 2, 8, 1};
for (int i = 0; i < 4; i++) {
    priority_queue_push(&pq, &values[i]);
}
priority_queue_pop(&pq);

// Access top
int* top = (int*)priority_queue_top(&pq);

// Information
size_t pq_size = priority_queue_size(&pq);
bool pq_empty = priority_queue_empty(&pq);

// Cleanup
priority_queue_free(&pq);

Deque Operations

// Initialization
deque dq;
deque_init(&dq, sizeof(int));

// Push operations
int value = 15;
deque_push_front(&dq, &value);
deque_push_back(&dq, &value);

// Pop operations
deque_pop_front(&dq);
deque_pop_back(&dq);

// Access
int* front = (int*)deque_front(&dq);
int* back = (int*)deque_back(&dq);

// Information
size_t deque_size = deque_size(&dq);
bool deque_empty = deque_empty(&dq);

// Cleanup
deque_free(&dq);

Linked List Operations

// Initialization
list l;
list_init(&l, sizeof(int));

// Push operations
int value = 25;
list_push_front(&l, &value);
list_push_back(&l, &value);

// Pop operations
list_pop_front(&l);
list_pop_back(&l);

// Insertion and deletion
list_insert(&l, index, &value);
list_erase(&l, index);

// Access
int* front = (int*)list_front(&l);
int* back = (int*)list_back(&l);

// Information
size_t list_size = list_size(&l);
bool list_empty = list_empty(&l);

// Cleanup
list_free(&l);

Sorting Algorithms

int arr[] = {5, 2, 8, 1, 9};
size_t length = 5;

// Bubble Sort
bubble_sort(arr, sizeof(int), length, compare_int);

// Insertion Sort
insertion_sort(arr, sizeof(int), length, compare_int);

// Selection Sort
selection_sort(arr, sizeof(int), length, compare_int);

// Merge Sort
merge_sort(arr, sizeof(int), length, compare_int);

// Quick Sort
quick_sort(arr, sizeof(int), length, compare_int);

// Heap Sort
heap_sort(arr, sizeof(int), length, compare_int);

// Counting Sort (integer arrays only)
counting_sort(arr, length);

// Radix Sort (integer arrays only)
radix_sort(arr, length);

// Check if sorted
bool sorted = is_sorted(arr, sizeof(int), length, compare_int);

Searching Algorithms

int arr[] = {1, 2, 3, 4, 5, 5, 6};
size_t length = 7;
int key = 5;

// Linear Search
int index = linear_search(arr, sizeof(int), length, &key, compare_int);

// Binary Search (requires sorted array)
int bin_index = binary_search(arr, sizeof(int), length, &key, compare_int);

// Binary Search First Occurrence
int first_index = binary_search_first(arr, sizeof(int), length, &key, compare_int);

// Binary Search Last Occurrence
int last_index = binary_search_last(arr, sizeof(int), length, &key, compare_int);

// Exponential Search
int exp_index = exponential_search(arr, sizeof(int), length, &key, compare_int);

// Jump Search
int jump_index = jump_search(arr, sizeof(int), length, &key, compare_int);

// Interpolation Search (integer arrays only)
int interp_index = interpolation_search(arr, length, key);

Utility Algorithms

int arr[] = {1, 2, 3, 2, 4, 2, 5};
size_t length = 7;
int target = 2;

// Finding elements
int found_index = find(arr, sizeof(int), length, &target, compare_int);
int found_if_index = find_if(arr, sizeof(int), length, is_even_predicate);

// Counting elements
int count = count(arr, sizeof(int), length, &target, compare_int);
int count_if_result = count_if(arr, sizeof(int), length, is_even_predicate);

// Min/Max elements
int* min_elem = (int*)min_element(arr, sizeof(int), length, compare_int);
int* max_elem = (int*)max_element(arr, sizeof(int), length, compare_int);

// Accumulation
int sum = 0;
accumulate(arr, sizeof(int), length, &sum, add_elements);

// For Each
for_each(arr, sizeof(int), length, print_element);

// Copying
int dest[7];
copy(arr, dest, sizeof(int), length);

// Conditional Copy
size_t copied_count;
copy_if(arr, dest, sizeof(int), length, is_even_predicate, &copied_count);

// Filling
int fill_value = 0;
fill(arr, sizeof(int), length, &fill_value);

// Transformation
transform(src, dest, sizeof(int), length, square_element);

// Partitioning
size_t partition_idx;
partition(arr, sizeof(int), length, is_even_predicate, &partition_idx);

// Rotation
rotate(arr, sizeof(int), length, 2); // Rotate left by 2 positions

// Unique elements
size_t new_length;
unique(arr, sizeof(int), length, compare_int, &new_length);

// Nth element (partial sort)
nth_element(arr, sizeof(int), length, 3, compare_int); // 4th smallest element

// Permutation check
bool is_perm = is_permutation(arr1, arr2, sizeof(int), length, compare_int);

String Utilities

// Splitting strings
int count;
char** tokens = string_split("hello,world,test", ",", &count);
// Use tokens...
for (int i = 0; i < count; i++) free(tokens[i]);
free(tokens);

// Joining strings
char* arr[] = {"hello", "world", "test"};
char* joined = string_join(arr, 3, ", ");
// Use joined...
free(joined);

// Trimming
char* trimmed = string_trim("   hello world   ");
// Use trimmed...
free(trimmed);

// Case conversion
char* upper = string_to_upper("Hello");
char* lower = string_to_lower("Hello");
// Use upper/lower...
free(upper);
free(lower);

// Replacement
char* replaced = string_replace("hello world", "world", "there");
// Use replaced...
free(replaced);

// Checks
bool starts = string_starts_with("hello world", "hello");
bool ends = string_ends_with("hello world", "world");
bool contains = string_contains("hello world", "lo wo");

// Reverse
char* reversed = string_reverse("hello");
// Use reversed...
free(reversed);

// Case-insensitive comparison
int cmp = string_compare_nocase("Hello", "hello"); // Returns 0

// Duplication
char* dup = string_duplicate("hello");
// Use dup...
free(dup);

Random Utilities

// Seeding
random_seed((unsigned int)time(NULL));

// Random numbers
int rand_int = random_int(1, 100);
double rand_float = random_float(0.0, 1.0);

// Shuffling arrays
int arr[] = {1, 2, 3, 4, 5};
shuffle(arr, sizeof(int), 5);

// Random choice
int* choice = (int*)random_choice(arr, sizeof(int), 5);

Timer Utilities

// Timing code execution
clock_t start;
double start_time = timer_start(&start);

// Code to time...
for (int i = 0; i < 1000000; i++) { }

double elapsed = timer_end(start);
printf("Elapsed time: %f seconds\n", elapsed);

// Sleep
sleep_ms(1000); // Sleep for 1 second

Math Utilities

// Comparisons
int a = 5, b = 10;
int* min_val = (int*)min(&a, &b, compare_int);
int* max_val = (int*)max(&a, &b, compare_int);

// Clamping
int value = 15, low = 0, high = 10;
clamp(&value, &low, &high, sizeof(int), compare_int);
// value is now 10

// Basic math
int absolute = abs_val(-5); // 5
long long gcd_val = gcd(48, 18); // 6
long long lcm_val = lcm(12, 18); // 36
bool prime = is_prime(17); // true
long long power_val = power(2, 8); // 256

Memory Utilities

// Safe memory allocation
int* arr = (int*)safe_malloc(10 * sizeof(int));
arr = (int*)safe_realloc(arr, 20 * sizeof(int));
int* zero_arr = (int*)safe_calloc(10, sizeof(int));

// Don't forget to free!
free(arr);
free(zero_arr);

Comparator Helpers

// Built-in comparators
int cmp_int = compare_int(&a, &b);
int cmp_float = compare_float(&f1, &f2);
int cmp_str = compare_string(&str1, &str2);

// Reverse comparator
int (*reverse_cmp)(const void*, const void*) = 
    (int (*)(const void*, const void*))compare_reverse;
int rev_cmp = reverse_cmp(&a, &b, compare_int);

// Example predicate functions
bool is_even_predicate(void* element) {
    int* value = (int*)element;
    return *value % 2 == 0;
}

void add_elements(void* result, void* element) {
    int* sum = (int*)result;
    int* value = (int*)element;
    *sum += *value;
}

void print_element(void* element) {
    int* value = (int*)element;
    printf("%d ", *value);
}

void square_element(void* src, void* dest) {
    int* src_val = (int*)src;
    int* dest_val = (int*)dest;
    *dest_val = (*src_val) * (*src_val);
}

Complete Example Usage

#include "cstl.h"
#include <stdio.h>

int main() {
    // Vector example
    vector v;
    vector_init(&v, sizeof(int));
    
    for (int i = 0; i < 10; i++) {
        vector_push_back(&v, &i);
    }
    
    printf("Vector size: %zu\n", vector_size(&v));
    
    for (size_t i = 0; i < vector_size(&v); i++) {
        int* elem = (int*)vector_get(&v, i);
        printf("%d ", *elem);
    }
    printf("\n");
    
    vector_free(&v);
    
    // Map example
    unordered_map m;
    map_init(&m);
    
    int values[] = {100, 200, 300};
    map_insert(&m, "key1", &values[0], sizeof(int));
    map_insert(&m, "key2", &values[1], sizeof(int));
    
    int* retrieved = (int*)map_get(&m, "key1");
    if (retrieved) {
        printf("Value for key1: %d\n", *retrieved);
    }
    
    map_free(&m);
    
    // Sorting example
    int arr[] = {5, 2, 8, 1, 9};
    size_t len = 5;
    
    quick_sort(arr, sizeof(int), len, compare_int);
    
    printf("Sorted array: ");
    for (size_t i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}
  • This comprehensive C STL library provides type-safe, generic containers and algorithms similar to C++ STL, making data structure manipulation in C much more convenient and safe.

C STL Library - Complete Examples with All Data Types

Table of Contents
    • Basic Data Types
    • Structures and Custom Types
    • String Operations
    • Complex Data Structures
    • Mixed Type Examples

Basic Data Types

Integer Examples

#include "cstl.h"
#include <stdio.h>

void integer_examples() {
    printf("=== INTEGER EXAMPLES ===\n");
    
    // Vector of integers
    vector int_vec;
    vector_init(&int_vec, sizeof(int));
    
    int numbers[] = {10, 20, 30, 40, 50};
    for (int i = 0; i < 5; i++) {
        vector_push_back(&int_vec, &numbers[i]);
    }
    
    printf("Integer vector: ");
    for (size_t i = 0; i < vector_size(&int_vec); i++) {
        int* val = (int*)vector_get(&int_vec, i);
        printf("%d ", *val);
    }
    printf("\n");
    
    // Map with integer values
    unordered_map int_map;
    map_init(&int_map);
    
    int map_values[] = {100, 200, 300};
    map_insert(&int_map, "age", &map_values[0], sizeof(int));
    map_insert(&int_map, "score", &map_values[1], sizeof(int));
    map_insert(&int_map, "count", &map_values[2], sizeof(int));
    
    int* age = (int*)map_get(&int_map, "age");
    if (age) {
        printf("Age from map: %d\n", *age);
    }
    
    // Set of integers
    set int_set;
    set_init(&int_set, sizeof(int), compare_int);
    
    int set_values[] = {1, 2, 3, 2, 1, 4, 5};
    for (int i = 0; i < 7; i++) {
        set_insert(&int_set, &set_values[i]);
    }
    
    printf("Integer set (unique values): ");
    for (size_t i = 0; i < set_size(&int_set); i++) {
        int* val = (int*)vector_get((vector*)&int_set, i);
        printf("%d ", *val);
    }
    printf("\n");
    
    // Sorting integers
    int sort_arr[] = {64, 34, 25, 12, 22, 11, 90};
    size_t sort_len = 7;
    
    quick_sort(sort_arr, sizeof(int), sort_len, compare_int);
    
    printf("Sorted integers: ");
    for (size_t i = 0; i < sort_len; i++) {
        printf("%d ", sort_arr[i]);
    }
    printf("\n");
    
    // Cleanup
    vector_free(&int_vec);
    map_free(&int_map);
    set_free(&int_set);
}

Float/Double Examples

void float_examples() {
    printf("\n=== FLOAT/DOUBLE EXAMPLES ===\n");
    
    // Vector of doubles
    vector double_vec;
    vector_init(&double_vec, sizeof(double));
    
    double temperatures[] = {23.5, 18.7, 32.1, 15.3, 27.8};
    for (int i = 0; i < 5; i++) {
        vector_push_back(&double_vec, &temperatures[i]);
    }
    
    printf("Double vector: ");
    for (size_t i = 0; i < vector_size(&double_vec); i++) {
        double* val = (double*)vector_get(&double_vec, i);
        printf("%.1f ", *val);
    }
    printf("\n");
    
    // Map with float values
    unordered_map float_map;
    map_init(&float_map);
    
    float prices[] = {19.99f, 29.99f, 9.99f};
    map_insert(&float_map, "book", &prices[0], sizeof(float));
    map_insert(&float_map, "shirt", &prices[1], sizeof(float));
    map_insert(&float_map, "coffee", &prices[2], sizeof(float));
    
    float* book_price = (float*)map_get(&float_map, "book");
    if (book_price) {
        printf("Book price: $%.2f\n", *book_price);
    }
    
    // Sorting doubles
    double double_arr[] = {3.14, 2.71, 1.41, 1.73, 0.57};
    size_t double_len = 5;
    
    bubble_sort(double_arr, sizeof(double), double_len, compare_float);
    
    printf("Sorted doubles: ");
    for (size_t i = 0; i < double_len; i++) {
        printf("%.2f ", double_arr[i]);
    }
    printf("\n");
    
    // Priority queue with doubles
    priority_queue double_pq;
    priority_queue_init(&double_pq, sizeof(double), compare_float);
    
    double pq_values[] = {5.5, 2.2, 8.8, 1.1, 9.9};
    for (int i = 0; i < 5; i++) {
        priority_queue_push(&double_pq, &pq_values[i]);
    }
    
    printf("Priority queue (max first): ");
    while (!priority_queue_empty(&double_pq)) {
        double* top = (double*)priority_queue_top(&double_pq);
        printf("%.1f ", *top);
        priority_queue_pop(&double_pq);
    }
    printf("\n");
    
    // Cleanup
    vector_free(&double_vec);
    map_free(&float_map);
    priority_queue_free(&double_pq);
}

Character Examples

void char_examples() {
    printf("\n=== CHARACTER EXAMPLES ===\n");
    
    // Vector of characters
    vector char_vec;
    vector_init(&char_vec, sizeof(char));
    
    char letters[] = {'A', 'B', 'C', 'D', 'E'};
    for (int i = 0; i < 5; i++) {
        vector_push_back(&char_vec, &letters[i]);
    }
    
    printf("Character vector: ");
    for (size_t i = 0; i < vector_size(&char_vec); i++) {
        char* val = (char*)vector_get(&char_vec, i);
        printf("%c ", *val);
    }
    printf("\n");
    
    // Set of characters
    set char_set;
    set_init(&char_set, sizeof(char), compare_int); // chars are integers
    
    char set_chars[] = {'a', 'b', 'c', 'a', 'b', 'd'};
    for (int i = 0; i < 6; i++) {
        set_insert(&char_set, &set_chars[i]);
    }
    
    printf("Character set (unique): ");
    for (size_t i = 0; i < set_size(&char_set); i++) {
        char* val = (char*)vector_get((vector*)&char_set, i);
        printf("%c ", *val);
    }
    printf("\n");
    
    // Stack of characters
    stack char_stack;
    stack_init(&char_stack, sizeof(char));
    
    char stack_chars[] = {'X', 'Y', 'Z'};
    for (int i = 0; i < 3; i++) {
        stack_push(&char_stack, &stack_chars[i]);
    }
    
    printf("Stack pop order: ");
    while (!stack_empty(&char_stack)) {
        char* top = (char*)stack_top(&char_stack);
        printf("%c ", *top);
        stack_pop(&char_stack);
    }
    printf("\n");
    
    // Cleanup
    vector_free(&char_vec);
    set_free(&char_set);
    stack_free(&char_stack);
}

Boolean Examples

void bool_examples() {
    printf("\n=== BOOLEAN EXAMPLES ===\n");
    
    // Vector of booleans
    vector bool_vec;
    vector_init(&bool_vec, sizeof(bool));
    
    bool flags[] = {true, false, true, true, false};
    for (int i = 0; i < 5; i++) {
        vector_push_back(&bool_vec, &flags[i]);
    }
    
    printf("Boolean vector: ");
    for (size_t i = 0; i < vector_size(&bool_vec); i++) {
        bool* val = (bool*)vector_get(&bool_vec, i);
        printf("%s ", *val ? "true" : "false");
    }
    printf("\n");
    
    // Count true values using count_if
    int true_count = count_if(bool_vec.data, sizeof(bool), vector_size(&bool_vec), 
                             [](void* elem) { return *(bool*)elem; });
    printf("Number of true values: %d\n", true_count);
    
    // Queue of booleans
    queue bool_queue;
    queue_init(&bool_queue, sizeof(bool));
    
    bool queue_bools[] = {true, false, true};
    for (int i = 0; i < 3; i++) {
        queue_enqueue(&bool_queue, &queue_bools[i]);
    }
    
    printf("Queue values: ");
    while (!queue_empty(&bool_queue)) {
        bool* front = (bool*)queue_front(&bool_queue);
        printf("%s ", *front ? "true" : "false");
        queue_dequeue(&bool_queue);
    }
    printf("\n");
    
    // Cleanup
    vector_free(&bool_vec);
    queue_free(&bool_queue);
}

Structures and Custom Types

Person Structure Example

typedef struct {
    char name[50];
    int age;
    double salary;
} Person;

// Comparator for Person by age
int compare_person_by_age(const void* a, const void* b) {
    const Person* p1 = (const Person*)a;
    const Person* p2 = (const Person*)b;
    return (p1->age > p2->age) - (p1->age < p2->age);
}

// Comparator for Person by salary
int compare_person_by_salary(const void* a, const void* b) {
    const Person* p1 = (const Person*)a;
    const Person* p2 = (const Person*)b;
    return (p1->salary > p2->salary) - (p1->salary < p2->salary);
}

// Comparator for Person by name
int compare_person_by_name(const void* a, const void* b) {
    const Person* p1 = (const Person*)a;
    const Person* p2 = (const Person*)b;
    return strcmp(p1->name, p2->name);
}

void person_examples() {
    printf("\n=== PERSON STRUCTURE EXAMPLES ===\n");
    
    // Vector of Person structures
    vector person_vec;
    vector_init(&person_vec, sizeof(Person));
    
    Person people[] = {
        {"Alice", 30, 50000.0},
        {"Bob", 25, 45000.0},
        {"Charlie", 35, 60000.0},
        {"Diana", 28, 52000.0}
    };
    
    for (int i = 0; i < 4; i++) {
        vector_push_back(&person_vec, &people[i]);
    }
    
    printf("People vector:\n");
    for (size_t i = 0; i < vector_size(&person_vec); i++) {
        Person* p = (Person*)vector_get(&person_vec, i);
        printf("  %s, Age: %d, Salary: $%.2f\n", p->name, p->age, p->salary);
    }
    
    // Sort by age
    quick_sort(person_vec.data, sizeof(Person), vector_size(&person_vec), 
               compare_person_by_age);
    
    printf("\nSorted by age:\n");
    for (size_t i = 0; i < vector_size(&person_vec); i++) {
        Person* p = (Person*)vector_get(&person_vec, i);
        printf("  %s, Age: %d\n", p->name, p->age);
    }
    
    // Sort by salary
    quick_sort(person_vec.data, sizeof(Person), vector_size(&person_vec), 
               compare_person_by_salary);
    
    printf("\nSorted by salary:\n");
    for (size_t i = 0; i < vector_size(&person_vec); i++) {
        Person* p = (Person*)vector_get(&person_vec, i);
        printf("  %s, Salary: $%.2f\n", p->name, p->salary);
    }
    
    // Map with Person values
    unordered_map person_map;
    map_init(&person_map);
    
    Person bob = {"Bob Smith", 40, 75000.0};
    Person alice = {"Alice Johnson", 35, 80000.0};
    
    map_insert(&person_map, "employee1", &bob, sizeof(Person));
    map_insert(&person_map, "employee2", &alice, sizeof(Person));
    
    Person* retrieved = (Person*)map_get(&person_map, "employee1");
    if (retrieved) {
        printf("\nRetrieved employee: %s, Age: %d\n", retrieved->name, retrieved->age);
    }
    
    // Set of Person (by name)
    set person_set;
    set_init(&person_set, sizeof(Person), compare_person_by_name);
    
    Person unique_people[] = {
        {"John", 25, 40000.0},
        {"Jane", 30, 50000.0},
        {"John", 35, 60000.0} // Duplicate name
    };
    
    for (int i = 0; i < 3; i++) {
        set_insert(&person_set, &unique_people[i]);
    }
    
    printf("\nUnique people by name (set size: %zu):\n", set_size(&person_set));
    for (size_t i = 0; i < set_size(&person_set); i++) {
        Person* p = (Person*)vector_get((vector*)&person_set, i);
        printf("  %s, Age: %d\n", p->name, p->age);
    }
    
    // Cleanup
    vector_free(&person_vec);
    map_free(&person_map);
    set_free(&person_set);
}

Point Structure Example

typedef struct {
    int x;
    int y;
} Point;

// Comparator for Point by x coordinate
int compare_point_by_x(const void* a, const void* b) {
    const Point* p1 = (const Point*)a;
    const Point* p2 = (const Point*)b;
    return (p1->x > p2->x) - (p1->x < p2->x);
}

// Comparator for Point by y coordinate
int compare_point_by_y(const void* a, const void* b) {
    const Point* p1 = (const Point*)a;
    const Point* p2 = (const Point*)b;
    return (p1->y > p2->y) - (p1->y < p2->y);
}

// Distance from origin comparator
int compare_point_by_distance(const void* a, const void* b) {
    const Point* p1 = (const Point*)a;
    const Point* p2 = (const Point*)b;
    double dist1 = sqrt(p1->x * p1->x + p1->y * p1->y);
    double dist2 = sqrt(p2->x * p2->x + p2->y * p2->y);
    return (dist1 > dist2) - (dist1 < dist2);
}

void point_examples() {
    printf("\n=== POINT STRUCTURE EXAMPLES ===\n");
    
    // Vector of Points
    vector point_vec;
    vector_init(&point_vec, sizeof(Point));
    
    Point points[] = {
        {1, 2}, {3, 4}, {5, 1}, {2, 7}, {4, 3}
    };
    
    for (int i = 0; i < 5; i++) {
        vector_push_back(&point_vec, &points[i]);
    }
    
    printf("Points vector:\n");
    for (size_t i = 0; i < vector_size(&point_vec); i++) {
        Point* p = (Point*)vector_get(&point_vec, i);
        printf("  (%d, %d)\n", p->x, p->y);
    }
    
    // Sort by x coordinate
    quick_sort(point_vec.data, sizeof(Point), vector_size(&point_vec), 
               compare_point_by_x);
    
    printf("\nSorted by x coordinate:\n");
    for (size_t i = 0; i < vector_size(&point_vec); i++) {
        Point* p = (Point*)vector_get(&point_vec, i);
        printf("  (%d, %d)\n", p->x, p->y);
    }
    
    // Sort by distance from origin
    quick_sort(point_vec.data, sizeof(Point), vector_size(&point_vec), 
               compare_point_by_distance);
    
    printf("\nSorted by distance from origin:\n");
    for (size_t i = 0; i < vector_size(&point_vec); i++) {
        Point* p = (Point*)vector_get(&point_vec, i);
        double dist = sqrt(p->x * p->x + p->y * p->y);
        printf("  (%d, %d) - distance: %.2f\n", p->x, p->y, dist);
    }
    
    // Deque of Points
    deque point_deque;
    deque_init(&point_deque, sizeof(Point));
    
    Point front_point = {0, 0};
    Point back_point = {10, 10};
    
    deque_push_front(&point_deque, &front_point);
    deque_push_back(&point_deque, &back_point);
    
    printf("\nDeque front: (%d, %d)\n", 
           ((Point*)deque_front(&point_deque))->x,
           ((Point*)deque_front(&point_deque))->y);
    printf("Deque back: (%d, %d)\n",
           ((Point*)deque_back(&point_deque))->x,
           ((Point*)deque_back(&point_deque))->y);
    
    // Cleanup
    vector_free(&point_vec);
    deque_free(&point_deque);
}

String Operations

C-String Examples

void string_examples() {
    printf("\n=== STRING OPERATIONS ===\n");
    
    // Vector of strings (char*)
    vector str_vec;
    vector_init(&str_vec, sizeof(char*));
    
    char* names[] = {"Alice", "Bob", "Charlie", "Diana", "Eve"};
    for (int i = 0; i < 5; i++) {
        char* name_copy = string_duplicate(names[i]);
        vector_push_back(&str_vec, &name_copy);
    }
    
    printf("String vector: ");
    for (size_t i = 0; i < vector_size(&str_vec); i++) {
        char** name_ptr = (char**)vector_get(&str_vec, i);
        printf("%s ", *name_ptr);
    }
    printf("\n");
    
    // Sort strings
    quick_sort(str_vec.data, sizeof(char*), vector_size(&str_vec), compare_string);
    
    printf("Sorted strings: ");
    for (size_t i = 0; i < vector_size(&str_vec); i++) {
        char** name_ptr = (char**)vector_get(&str_vec, i);
        printf("%s ", *name_ptr);
    }
    printf("\n");
    
    // Map with string keys and values
    unordered_map str_map;
    map_init(&str_map);
    
    char* capitals[] = {"France", "Germany", "Italy"};
    char* cities[] = {"Paris", "Berlin", "Rome"};
    
    for (int i = 0; i < 3; i++) {
        map_insert(&str_map, capitals[i], &cities[i], sizeof(char*));
    }
    
    char** capital = (char**)map_get(&str_map, "France");
    if (capital) {
        printf("Capital of France: %s\n", *capital);
    }
    
    // String splitting and joining
    char* text = "apple,banana,cherry,date";
    int token_count;
    char** tokens = string_split(text, ",", &token_count);
    
    printf("Split tokens (%d): ", token_count);
    for (int i = 0; i < token_count; i++) {
        printf("%s ", tokens[i]);
    }
    printf("\n");
    
    char* joined = string_join(tokens, token_count, " | ");
    printf("Joined string: %s\n", joined);
    
    // String transformations
    char* original = "   Hello World!   ";
    char* trimmed = string_trim(original);
    char* upper = string_to_upper(trimmed);
    char* lower = string_to_lower(trimmed);
    
    printf("Original: '%s'\n", original);
    printf("Trimmed: '%s'\n", trimmed);
    printf("Upper: '%s'\n", upper);
    printf("Lower: '%s'\n", lower);
    
    // String replacement
    char* sentence = "I like cats and cats like me";
    char* replaced = string_replace(sentence, "cats", "dogs");
    printf("Replaced: %s\n", replaced);
    
    // Cleanup
    for (size_t i = 0; i < vector_size(&str_vec); i++) {
        char** name_ptr = (char**)vector_get(&str_vec, i);
        free(*name_ptr);
    }
    vector_free(&str_vec);
    map_free(&str_map);
    
    for (int i = 0; i < token_count; i++) {
        free(tokens[i]);
    }
    free(tokens);
    free(joined);
    free(trimmed);
    free(upper);
    free(lower);
    free(replaced);
}

Complex Data Structures

Nested Structures Example

typedef struct {
    char title[100];
    char author[50];
    int year;
    double price;
} Book;

typedef struct {
    char name[100];
    vector books; // vector of Book
} Library;

int compare_book_by_title(const void* a, const void* b) {
    const Book* b1 = (const Book*)a;
    const Book* b2 = (const Book*)b;
    return strcmp(b1->title, b2->title);
}

int compare_book_by_year(const void* a, const void* b) {
    const Book* b1 = (const Book*)a;
    const Book* b2 = (const Book*)b;
    return (b1->year > b2->year) - (b1->year < b2->year);
}

void library_examples() {
    printf("\n=== LIBRARY (NESTED STRUCTURES) EXAMPLE ===\n");
    
    // Create books
    Book book1 = {"The Great Gatsby", "F. Scott Fitzgerald", 1925, 12.99};
    Book book2 = {"1984", "George Orwell", 1949, 10.99};
    Book book3 = {"To Kill a Mockingbird", "Harper Lee", 1960, 11.99};
    Book book4 = {"Pride and Prejudice", "Jane Austen", 1813, 9.99};
    
    // Create library
    Library library;
    strcpy(library.name, "City Central Library");
    vector_init(&library.books, sizeof(Book));
    
    // Add books to library
    vector_push_back(&library.books, &book1);
    vector_push_back(&library.books, &book2);
    vector_push_back(&library.books, &book3);
    vector_push_back(&library.books, &book4);
    
    printf("Library: %s\n", library.name);
    printf("Books (%zu):\n", vector_size(&library.books));
    for (size_t i = 0; i < vector_size(&library.books); i++) {
        Book* book = (Book*)vector_get(&library.books, i);
        printf("  '%s' by %s (%d) - $%.2f\n", 
               book->title, book->author, book->year, book->price);
    }
    
    // Sort books by title
    quick_sort(library.books.data, sizeof(Book), vector_size(&library.books), 
               compare_book_by_title);
    
    printf("\nBooks sorted by title:\n");
    for (size_t i = 0; i < vector_size(&library.books); i++) {
        Book* book = (Book*)vector_get(&library.books, i);
        printf("  %s\n", book->title);
    }
    
    // Sort books by year
    quick_sort(library.books.data, sizeof(Book), vector_size(&library.books), 
               compare_book_by_year);
    
    printf("\nBooks sorted by year:\n");
    for (size_t i = 0; i < vector_size(&library.books); i++) {
        Book* book = (Book*)vector_get(&library.books, i);
        printf("  %s (%d)\n", book->title, book->year);
    }
    
    // Find books after 1950
    printf("\nBooks published after 1950:\n");
    for (size_t i = 0; i < vector_size(&library.books); i++) {
        Book* book = (Book*)vector_get(&library.books, i);
        if (book->year > 1950) {
            printf("  %s (%d)\n", book->title, book->year);
        }
    }
    
    // Cleanup
    vector_free(&library.books);
}

Mixed Type Container Example

typedef enum { INT_TYPE, DOUBLE_TYPE, STRING_TYPE } DataType;

typedef struct {
    DataType type;
    union {
        int int_value;
        double double_value;
        char* string_value;
    };
} Variant;

int compare_variant(const void* a, const void* b) {
    const Variant* v1 = (const Variant*)a;
    const Variant* v2 = (const Variant*)b;
    
    if (v1->type != v2->type) {
        return v1->type - v2->type;
    }
    
    switch (v1->type) {
        case INT_TYPE:
            return compare_int(&v1->int_value, &v2->int_value);
        case DOUBLE_TYPE:
            return compare_float(&v1->double_value, &v2->double_value);
        case STRING_TYPE:
            return compare_string(&v1->string_value, &v2->string_value);
        default:
            return 0;
    }
}

void variant_examples() {
    printf("\n=== VARIANT (MIXED TYPES) EXAMPLE ===\n");
    
    vector variant_vec;
    vector_init(&variant_vec, sizeof(Variant));
    
    // Add different types
    Variant v1 = {INT_TYPE, .int_value = 42};
    Variant v2 = {DOUBLE_TYPE, .double_value = 3.14159};
    Variant v3 = {STRING_TYPE, .string_value = string_duplicate("Hello")};
    Variant v4 = {INT_TYPE, .int_value = 100};
    Variant v5 = {DOUBLE_TYPE, .double_value = 2.71828};
    
    vector_push_back(&variant_vec, &v1);
    vector_push_back(&variant_vec, &v2);
    vector_push_back(&variant_vec, &v3);
    vector_push_back(&variant_vec, &v4);
    vector_push_back(&variant_vec, &v5);
    
    printf("Variant vector:\n");
    for (size_t i = 0; i < vector_size(&variant_vec); i++) {
        Variant* v = (Variant*)vector_get(&variant_vec, i);
        switch (v->type) {
            case INT_TYPE:
                printf("  INT: %d\n", v->int_value);
                break;
            case DOUBLE_TYPE:
                printf("  DOUBLE: %.5f\n", v->double_value);
                break;
            case STRING_TYPE:
                printf("  STRING: %s\n", v->string_value);
                break;
        }
    }
    
    // Sort variants
    quick_sort(variant_vec.data, sizeof(Variant), vector_size(&variant_vec), 
               compare_variant);
    
    printf("\nSorted variants:\n");
    for (size_t i = 0; i < vector_size(&variant_vec); i++) {
        Variant* v = (Variant*)vector_get(&variant_vec, i);
        switch (v->type) {
            case INT_TYPE:
                printf("  INT: %d\n", v->int_value);
                break;
            case DOUBLE_TYPE:
                printf("  DOUBLE: %.5f\n", v->double_value);
                break;
            case STRING_TYPE:
                printf("  STRING: %s\n", v->string_value);
                break;
        }
    }
    
    // Cleanup
    for (size_t i = 0; i < vector_size(&variant_vec); i++) {
        Variant* v = (Variant*)vector_get(&variant_vec, i);
        if (v->type == STRING_TYPE) {
            free(v->string_value);
        }
    }
    vector_free(&variant_vec);
}

Mixed Type Examples

Comprehensive Example with All Containers

void comprehensive_example() {
    printf("\n=== COMPREHENSIVE EXAMPLE ===\n");
    
    // 1. Vector of different types
    vector int_vec, double_vec, str_vec;
    vector_init(&int_vec, sizeof(int));
    vector_init(&double_vec, sizeof(double));
    vector_init(&str_vec, sizeof(char*));
    
    // 2. Map with different value types
    unordered_map mixed_map;
    map_init(&mixed_map);
    
    // 3. Set of integers
    set int_set;
    set_init(&int_set, sizeof(int), compare_int);
    
    // 4. Stack and Queue
    stack int_stack;
    queue int_queue;
    stack_init(&int_stack, sizeof(int));
    queue_init(&int_queue, sizeof(int));
    
    // 5. Priority Queue
    priority_queue int_pq;
    priority_queue_init(&int_pq, sizeof(int), compare_int);
    
    // Populate data
    printf("Populating containers...\n");
    
    // Vector data
    for (int i = 1; i <= 5; i++) {
        vector_push_back(&int_vec, &i);
        double d = i * 1.1;
        vector_push_back(&double_vec, &d);
        
        char str[20];
        sprintf(str, "String%d", i);
        char* str_copy = string_duplicate(str);
        vector_push_back(&str_vec, &str_copy);
    }
    
    // Map data
    int age = 25;
    double salary = 50000.0;
    char* name = "John Doe";
    
    map_insert(&mixed_map, "age", &age, sizeof(int));
    map_insert(&mixed_map, "salary", &salary, sizeof(double));
    map_insert(&mixed_map, "name", &name, sizeof(char*));
    
    // Set data
    int set_values[] = {1, 2, 3, 2, 1, 4, 5};
    for (int i = 0; i < 7; i++) {
        set_insert(&int_set, &set_values[i]);
    }
    
    // Stack and Queue data
    for (int i = 1; i <= 3; i++) {
        stack_push(&int_stack, &i);
        queue_enqueue(&int_queue, &i);
    }
    
    // Priority Queue data
    int pq_values[] = {5, 2, 8, 1, 9};
    for (int i = 0; i < 5; i++) {
        priority_queue_push(&int_pq, &pq_values[i]);
    }
    
    // Display all data
    printf("\n=== DISPLAYING ALL CONTAINERS ===\n");
    
    printf("Integer Vector: ");
    for (size_t i = 0; i < vector_size(&int_vec); i++) {
        printf("%d ", *(int*)vector_get(&int_vec, i));
    }
    printf("\n");
    
    printf("Double Vector: ");
    for (size_t i = 0; i < vector_size(&double_vec); i++) {
        printf("%.1f ", *(double*)vector_get(&double_vec, i));
    }
    printf("\n");
    
    printf("String Vector: ");
    for (size_t i = 0; i < vector_size(&str_vec); i++) {
        printf("%s ", *(char**)vector_get(&str_vec, i));
    }
    printf("\n");
    
    printf("Mixed Map:\n");
    int* map_age = (int*)map_get(&mixed_map, "age");
    double* map_salary = (double*)map_get(&mixed_map, "salary");
    char** map_name = (char**)map_get(&mixed_map, "name");
    if (map_age) printf("  Age: %d\n", *map_age);
    if (map_salary) printf("  Salary: $%.2f\n", *map_salary);
    if (map_name) printf("  Name: %s\n", *map_name);
    
    printf("Integer Set: ");
    for (size_t i = 0; i < set_size(&int_set); i++) {
        printf("%d ", *(int*)vector_get((vector*)&int_set, i));
    }
    printf("\n");
    
    printf("Stack (LIFO): ");
    while (!stack_empty(&int_stack)) {
        printf("%d ", *(int*)stack_top(&int_stack));
        stack_pop(&int_stack);
    }
    printf("\n");
    
    printf("Queue (FIFO): ");
    while (!queue_empty(&int_queue)) {
        printf("%d ", *(int*)queue_front(&int_queue));
        queue_dequeue(&int_queue);
    }
    printf("\n");
    
    printf("Priority Queue: ");
    while (!priority_queue_empty(&int_pq)) {
        printf("%d ", *(int*)priority_queue_top(&int_pq));
        priority_queue_pop(&int_pq);
    }
    printf("\n");
    
    // Cleanup everything
    printf("\nCleaning up...\n");
    
    vector_free(&int_vec);
    vector_free(&double_vec);
    
    // Free string vector elements
    for (size_t i = 0; i < vector_size(&str_vec); i++) {
        char** str_ptr = (char**)vector_get(&str_vec, i);
        free(*str_ptr);
    }
    vector_free(&str_vec);
    
    map_free(&mixed_map);
    set_free(&int_set);
    stack_free(&int_stack);
    queue_free(&int_queue);
    priority_queue_free(&int_pq);
    
    printf("All containers cleaned up successfully!\n");
}

Using STL Containers in Loops

Vector Loops

#include "cstl.h"

vector numbers;
vector_init(&numbers, sizeof(int));

// Add some data
for (int i = 1; i <= 5; i++) {
    vector_push_back(&numbers, &i);
}

// METHOD 1: Regular for loop
printf("Method 1 - Regular for loop:\n");
for (size_t i = 0; i < vector_size(&numbers); i++) {
    int* num = (int*)vector_get(&numbers, i);
    printf("numbers[%zu] = %d\n", i, *num);
}

// METHOD 2: While loop
printf("\nMethod 2 - While loop:\n");
size_t index = 0;
while (index < vector_size(&numbers)) {
    int* num = (int*)vector_get(&numbers, index);
    printf("numbers[%zu] = %d\n", index, *num);
    index++;
}

vector_free(&numbers);

Map Loops (Limited - need to know keys)

#include "cstl.h"

unordered_map config;
map_init(&config);

// Add data
int port = 8080;
char* name = "Server";
map_insert(&config, "port", &port, sizeof(int));
map_insert(&config, "name", &name, sizeof(char*));

// Loop through known keys
printf("Map contents:\n");
const char* keys[] = {"port", "name"};
for (int i = 0; i < 2; i++) {
    void* value = map_get(&config, keys[i]);
    if (value) {
        if (strcmp(keys[i], "port") == 0) {
            printf("  %s: %d\n", keys[i], *(int*)value);
        } else {
            printf("  %s: %s\n", keys[i], *(char**)value);
        }
    }
}

map_free(&config);

Stack Loops (Destructive)

#include "cstl.h"

stack s;
stack_init(&s, sizeof(int));

// Add data
for (int i = 1; i <= 3; i++) {
    stack_push(&s, &i);
}

// Loop through stack (destroys it)
printf("Stack contents (LIFO order):\n");
while (!stack_empty(&s)) {
    int* top = (int*)stack_top(&s);
    printf("  %d\n", *top);
    stack_pop(&s);  // This removes the element
}

stack_free(&s);

Queue Loops (Destructive)

#include "cstl.h"

queue q;
queue_init(&q, sizeof(int));

// Add data
for (int i = 1; i <= 3; i++) {
    queue_enqueue(&q, &i);
}

// Loop through queue (destroys it)
printf("Queue contents (FIFO order):\n");
while (!queue_empty(&q)) {
    int* front = (int*)queue_front(&q);
    printf("  %d\n", *front);
    queue_dequeue(&q);  // This removes the element
}

queue_free(&q);

Practical Examples with Different Data Types

Strings in Vector:

#include "cstl.h"

vector names;
vector_init(&names, sizeof(char*));

// Add strings
char* name1 = "Alice";
char* name2 = "Bob";
char* name3 = "Charlie";
vector_push_back(&names, &name1);
vector_push_back(&names, &name2);
vector_push_back(&names, &name3);

// Loop through strings
printf("Names:\n");
for (size_t i = 0; i < vector_size(&names); i++) {
    char** name_ptr = (char**)vector_get(&names, i);
    printf("  %s\n", *name_ptr);
}

vector_free(&names);

Structures in Vector:

#include "cstl.h"

typedef struct {
    char name[50];
    int age;
} Person;

vector people;
vector_init(&people, sizeof(Person));

// Add people
Person p1 = {"Alice", 25};
Person p2 = {"Bob", 30};
Person p3 = {"Charlie", 35};
vector_push_back(&people, &p1);
vector_push_back(&people, &p2);
vector_push_back(&people, &p3);

// Loop through structures
printf("People:\n");
for (size_t i = 0; i < vector_size(&people); i++) {
    Person* person = (Person*)vector_get(&people, i);
    printf("  %s, %d years old\n", person->name, person->age);
}

vector_free(&people);

Advanced: Non-Destructive Stack/Queue Loops

#include "cstl.h"

// Non-destructive stack loop by using temporary stack
void print_stack_non_destructive(stack* s) {
    stack temp;
    stack_init(&temp, s->elementSize);
    
    printf("Stack contents (non-destructive):\n");
    
    // Copy to temp stack (reverses order)
    while (!stack_empty(s)) {
        void* top = stack_top(s);
        stack_push(&temp, top);
        stack_pop(s);
    }
    
    // Print and restore original stack
    while (!stack_empty(&temp)) {
        void* top = stack_top(&temp);
        int* value = (int*)top;
        printf("  %d\n", *value);
        stack_push(s, top);
        stack_pop(&temp);
    }
    
    stack_free(&temp);
}

// Usage
stack s;
stack_init(&s, sizeof(int));
int values[] = {1, 2, 3};
for (int i = 0; i < 3; i++) {
    stack_push(&s, &values[i]);
}

print_stack_non_destructive(&s);
printf("Original stack preserved, size: %zu\n", stack_size(&s));
stack_free(&s);

Complete Working Example

#include <stdio.h>
#include "cstl.h"

int main() {
    printf("=== STL CONTAINER LOOPS ===\n\n");
    
    // Vector loop example
    vector nums;
    vector_init(&nums, sizeof(int));
    
    for (int i = 10; i <= 50; i += 10) {
        vector_push_back(&nums, &i);
    }
    
    printf("Vector loop:\n");
    for (size_t i = 0; i < vector_size(&nums); i++) {
        int* num = (int*)vector_get(&nums, i);
        printf("  nums[%zu] = %d\n", i, *num);
    }
    
    // Modify elements in loop
    printf("\nModified vector:\n");
    for (size_t i = 0; i < vector_size(&nums); i++) {
        int* num = (int*)vector_get(&nums, i);
        *num *= 2;  // Double each value
        printf("  nums[%zu] = %d\n", i, *num);
    }
    
    vector_free(&nums);
    return 0;
}

Key Points:

1. Vectors: Use for (size_t i = 0; i < vector_size(&v); i++)
2. Maps: Need to know keys in advance (limitation of current implementation)
3. Stack/Queue: Loops are destructive by default
4. Always cast: (int*)vector_get(&v, i) or (char**) for strings
5. Modify in place: You can change values directly through pointers

Main Function to Run All Examples

int main() {
    printf("C STL LIBRARY - COMPLETE DATA TYPE EXAMPLES\n");
    printf("===========================================\n");
    
    integer_examples();
    float_examples();
    char_examples();
    bool_examples();
    person_examples();
    point_examples();
    string_examples();
    library_examples();
    variant_examples();
    comprehensive_example();
    
    printf("\nAll examples completed successfully!\n");
    return 0;
}

Key Features Demonstrated

1. All Basic Types: int, float, double, char, bool
2. Complex Structures: Person, Point, Book, Library
3. String Operations: C-strings with dynamic allocation
4. Mixed Types: Variant type using unions
5. All Containers: vector, map, set, stack, queue, priority_queue, deque, list
6. All Algorithms: Sorting, searching, utility functions
7. Memory Management: Proper allocation and cleanup
8. Type Safety: Generic containers with type-specific comparators
  • This comprehensive example suite demonstrates that the C STL library can handle virtually any data type you might need in real-world applications

About

No description or website provided.

Topics

Resources

License

Stars

Watchers

Forks

Languages