This project is a custom implementation of the C standard library functions, commonly known as "libft" in programming education. It includes both basic string and memory manipulation functions, as well as bonus linked list operations.
Libft is a foundational project that teaches:
- Memory management in C
- String manipulation without using standard library functions
- Linked list data structures
- Pointer arithmetic
- C programming best practices
A pointer is a variable that stores the memory address of another variable. Think of it as a "house address" that tells you where to find the actual data.
int number = 42; // A regular variable int *pointer = &number; // A pointer that stores the address of 'number'
Memory Layout:
βββββββββββββββ βββββββββββββββ
β number β β pointer β
β 42 β β 0x7fff... β
β 0x7fff... ββββββ β
βββββββββββββββ βββββββββββββββ
- Dynamic memory allocation: Create variables at runtime
- Pass by reference: Modify original variables in functions
- Data structures: Build complex structures like linked lists
- Efficiency: Avoid copying large data
Imagine you have a treasure map! πΊοΈ
- The treasure map is like a pointer - it doesn't have the treasure itself, but it tells you where to find it
- The treasure is like your data (a number, a word, etc.)
- The X marks the spot is like the memory address
π Your House (where you keep your toy box)
β
βΌ (your toy box is here!)
π¦ Toy Box = Your Data (like the number 42)
β
βΌ (this is your "map" to find it!)
πΊοΈ Treasure Map = Pointer (says "go to your house, find the toy box!")
When you follow the map β you find your toy! π
int my_toy = 42; // π¦ This is your toy (data) int *my_map = &my_toy; // πΊοΈ This is your map (pointer) // &my_toy means "where is my_toy located?"
Memory City:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π House 1: my_toy = 42 (your toy is here!) β
β π House 2: my_map = "go to House 1!" (your map) β
β π House 3: empty β
β π House 4: empty β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Your map (my_map) points to House 1 where your toy (42) lives! π β‘οΈπ¦
Remember: A pointer is just a friendly helper that remembers where your stuff is! π€
A linked list is a data structure where each element (node) contains data and a pointer to the next element.
typedef struct s_list { void *content; // The data stored in this node struct s_list *next; // Pointer to the next node } t_list;
Linked List Structure:
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Node 1 βββββΆ β Node 2 βββββΆ β Node 3 βββββΆ β NULL β
β content: "A"β β content: "B"β β content: "C"β β β
β next: βββββββ β next: βββββββ β next: βββββββ β β
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
Think of a linked list like a train with wagons:
π Train Adventure:
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β π Engine βββββΆ β π Wagon 1 βββββΆ | π Wagon 2 βββββΆ β π Wagon 3 β
β Driver: A β β Cargo: B β β Cargo: C β β Cargo: D β
β Next: ββββββ β Next: ββββββ β Next: ββββββ β Next: π β
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
How it works:
- Each wagon knows what's inside (cargo) π
- Each wagon knows which wagon comes next (next) β‘οΈ
- The last wagon points to nothing (π = NULL)
- You can add new wagons anywhere! π
- You can remove wagons without breaking the train! βοΈ
// π Create a train with one wagon t_list *train = ft_lstnew("Apple"); // Engine with an apple // π Add more wagons ft_lstadd_back(&train, ft_lstnew("Banana")); // Add banana wagon ft_lstadd_back(&train, ft_lstnew("Cherry")); // Add cherry wagon // πͺ Now your train is: Apple β Banana β Cherry β π
Memory Layout:
βββββββββββββββββββββββββββββββββββββββ
β Stack β
β (Automatic variables, function β
β parameters, return addresses) β
βββββββββββββββββββββββββββββββββββββββ€
β Heap β
β (Dynamically allocated memory β
β with malloc, calloc, realloc) β
βββββββββββββββββββββββββββββββββββββββ
Think of your computer's memory like different types of restaurants:
π½οΈ Computer Memory linked with Food:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π½οΈ Fast Food (Stack): β
β - Like McDonald's - quick service! β
β - You order, eat, and leave β
β - Staff cleans up automatically after you β
β - No need to worry about dishes β
β - Perfect for quick meals (small data) β
β β
β π½οΈ Your Kitchen (Heap): β
β - You prepare what you need (malloc) β
β - You decide how much to eat β
β - YOU MUST clean your own plate (free)! β
β - If you forget to clean β plates pile up! ποΈ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// π½οΈ Fast Food (Stack - automatic cleanup) int my_number = 42; // Order, eat, leave - staff cleans up! // π½οΈ Self-Service Buffet (Heap - manual cleanup) int *big_array = malloc(100 * sizeof(int)); // Take a big plate // ... use the plate ... free(big_array); // Clean your own plate!
Important:
- π½οΈ Stack = Fast food (automatic cleanup)
- π½οΈ Heap = your kitchen (YOU must clean up!)
- π§Ή Always clean your buffet plate (free) or dishes pile up! ποΈ
- π Both restaurants exist at the same time - no hierarchy!
String Functions:
βββ ft_strlen.c - Calculate string length
βββ ft_strchr.c - Find character in string
βββ ft_strrchr.c - Find last occurrence of character
βββ ft_strncmp.c - Compare strings
βββ ft_strnstr.c - Find substring
βββ ft_strdup.c - Duplicate string
βββ ft_substr.c - Extract substring
βββ ft_strjoin.c - Concatenate strings
βββ ft_strtrim.c - Remove characters from ends
βββ ft_split.c - Split string by delimiter
βββ ft_strmapi.c - Apply function to each character
βββ ft_striteri.c - Apply function with index
βββ ft_strlcpy.c - Copy string with size limit
βββ ft_strlcat.c - Concatenate with size limit
Memory Functions:
βββ ft_memset.c - Set memory to value
βββ ft_bzero.c - Set memory to zero
βββ ft_memcpy.c - Copy memory
βββ ft_memmove.c - Move memory (handles overlap)
βββ ft_memchr.c - Find byte in memory
βββ ft_memcmp.c - Compare memory
Character Functions:
βββ ft_isalpha.c - Check if alphabetic
βββ ft_isdigit.c - Check if digit
βββ ft_isalnum.c - Check if alphanumeric
βββ ft_isascii.c - Check if ASCII
βββ ft_isprint.c - Check if printable
βββ ft_toupper.c - Convert to uppercase
βββ ft_tolower.c - Convert to lowercase
Conversion Functions:
βββ ft_atoi.c - String to integer
βββ ft_itoa.c - Integer to string
βββ ft_calloc.c - Allocate and zero memory
Output Functions:
βββ ft_putchar_fd.c - Write character to file descriptor
βββ ft_putstr_fd.c - Write string to file descriptor
βββ ft_putendl_fd.c - Write string with newline
βββ ft_putnbr_fd.c - Write number to file descriptor
Linked List Functions:
βββ ft_lstnew.c - Create new list node
βββ ft_lstadd_front.c - Add node to beginning
βββ ft_lstadd_back.c - Add node to end
βββ ft_lstsize.c - Count nodes in list
βββ ft_lstlast.c - Find last node
βββ ft_lstdelone.c - Delete single node
βββ ft_lstclear.c - Delete entire list
βββ ft_lstiter.c - Apply function to each node
βββ ft_lstmap.c - Create new list with transformed data
# Compile the library make # Compile with bonus functions make bonus # Clean object files make clean # Clean everything make fclean # Recompile everything make re
#include "libft.h" int main(void) { // String operations char *str = "Hello, World!"; printf("Length: %zu\n", ft_strlen(str)); // Create a linked list t_list *list = ft_lstnew("First node"); ft_lstadd_back(&list, ft_lstnew("Second node")); // Print list size printf("List size: %d\n", ft_lstsize(list)); // Clean up ft_lstclear(&list, free); return (0); }
char *str = "Hello"; // str[0] is equivalent to *(str + 0) // str[1] is equivalent to *(str + 1)
- Always check if
mallocreturnsNULL - Free allocated memory to prevent memory leaks
- Be careful with buffer overflows
- C strings are null-terminated (
0ε) - String length doesn't include the null terminator
- Always allocate space for the null terminator
// Creating a new node t_list *new_node = ft_lstnew("data"); // Adding to front (becomes new head) ft_lstadd_front(&head, new_node); // Adding to back (becomes new tail) ft_lstadd_back(&head, new_node); // Traversing the list t_list *current = head; while (current != NULL) { // Process current->content current = current->next; }
- Forgetting to check malloc return: Always check if
mallocreturnsNULL - Buffer overflows: Don't write beyond allocated memory
- Memory leaks: Always free what you allocate
- Null pointer dereference: Check pointers before using them
- String length confusion: Remember null terminator
- Linked list cycles: Ensure the last node points to
NULL
You can test individual functions by uncommenting the test code at the bottom of each .c file and compiling with:
cc -Wall -Wextra -Werror ft_strlen.c -o test_strlen ./test_strlen
This is an educational project. Feel free to:
- Report bugs
- Suggest improvements
- Add more examples
- Improve documentation
Happy coding! π