Skip to content

Latest commit

 

History

History
302 lines (212 loc) · 10 KB

File metadata and controls

302 lines (212 loc) · 10 KB

My Libft

"C programming can be quite tedious without access to the highly useful standard functions. This project aims to help you understand how these functions work by implementing them yourself..."

— Your libft.pdf Subject

This project is my very first C library, a rite of passage at 42 School. It's a collection of re-coded libc functions, plus other useful utilities that I'll carry with me throughout my C projects.

C Language 42 Norm Makefile


##What's Inside?

This library is divided into three parts, just like the subject demands:

Part 1: The Libc Functions (The "Recode")

These are my own implementations of standard C functions. The goal was to perfectly mimic the behavior (and protect against the same errors) as the originals.

Character Tests Memory Functions String Functions
ft_isalpha ft_memset ft_strlen
ft_isdigit ft_bzero ft_strlcpy
ft_isalnum ft_memcpy ft_strlcat
ft_isascii ft_memmove ft_strchr
ft_isprint ft_memchr ft_strrchr
ft_toupper ft_memcmp ft_strncmp
ft_tolower ft_calloc ft_strnstr
ft_atoi ft_strdup

Part 2: The Additional Functions (The "Creations")

These functions are not in the standard libc but are incredibly useful. This is where memory allocation (malloc) becomes critical.

String Manipulation Conversion & Output
ft_substr ft_itoa
ft_strjoin ft_putchar_fd
ft_strtrim ft_putstr_fd
ft_split ft_putendl_fd
ft_strmapi ft_putnbr_fd
ft_striteri
## The main concepts i mastered

This project wasn't just about coding functions. It was a deep dive into the why of C. Here are the biggest lessons I learned.

1. The Treachery of Memory (And How to Tame It)

This project is where you truly face memory for the first time.

My Big Moment of realisation: Understanding the difference between ft_memcpy and ft_memmove

Memory Layout Example:

ft_memcpy - Fast but undefined with overlap: ┌─────┬─────┬─────┬─────┬─────┐ │src[0]│src[1]│ OVERLAP ZONE │dst[4]│ └─────┴─────┴─────┴─────┴─────┘ ⚠️ DANGEROUS!

ft_memmove - Safe with overlap detection: ┌─────┬─────┬─────┬─────┬─────┐ │src[0]│src[1]│ OVERLAP ZONE │dst[4]│ └─────┴─────┴─────┴─────┴─────┘ ✓ Checks direction and copies safely


**Key Concepts:**

| Concept | Explanation |
|---------|-------------|
| **`unsigned char *` casting** | Ensures byte-by-byte operations regardless of data type |
| **`ft_calloc` overflow check** | `if (nmemb > SIZE_MAX / size)` prevents integer overflow attacks |
| **`dest > src` check** | Determines copy direction to prevent data corruption in `ft_memmove` |

#### Reflection Point

**My biggest challenge in the memory functions was...**
> *Example: handling the `(unsigned char *)` casts correctly to avoid pointer arithmetic issues.*

**The `ft_calloc` overflow check taught me that...**
> *Example: security isn't just about NULL checks, but also about preventing integer overflows that lead to allocating the wrong amount of memory and causing a heap overflow.*

---

### 2. The Nightmare of C-Strings (And How to Survive It)

I learned that a "string" in C is just a `char*` with a `\0` at the end, and that concept is both simple and incredibly dangerous.

#### My second Big Moment of realisation: Why `ft_strlcpy` and `ft_strlcat` are safer

String Safety Comparison:

❌ UNSAFE ✅ SAFE ALTERNATIVE strcpy(dest, src) → ft_strlcpy(dest, src, size) strcat(dest, src) → ft_strlcat(dest, src, size)

Why? They take the full buffer size as an argument, guaranteeing NUL-termination and preventing buffer overflows.


#### Reflection Point

**My `ft_split` function wasn't just about finding a delimiter. It was a masterclass in...**
> *Example: complex memory management. I had to allocate the main array `char**`, then allocate each individual string `char*`. The most critical part was the error handling: if any single allocation failed, my `ft_memfree` helper had to go back and free everything I had already allocated to prevent a massive memory leak.*

---

### 3. Pointing at Functions (Like a Boss)

Part 2 and the Bonus introduced me to one of C's most powerful (and weirdest) features: function pointers.

#### My third Big Moment of realisation: The `ft_striteri` vs. `ft_strmapi` challenge

```c
// ft_striteri - Modifies in-place
void ft_striteri(char *s, void (*f)(unsigned int, char*));
// Takes char* - can modify the original string
// s is NOT const

// ft_strmapi - Creates new string
char *ft_strmapi(char const *s, char (*f)(unsigned int, char));
// Takes char (by value) - creates new content
// s IS const - never changes original

Function Pointer Comparison:

Function Signature Purpose
ft_striteri void (*f)(unsigned int, char*) Modifies original string in-place
ft_strmapi char (*f)(unsigned int, char) Creates new string, original stays const
ft_lstmap void *(*f)(...), void (*del)(...) Two pointers: one to transform, one to clean up on failure

Reflection Point

The bonus ft_lstmap function took this to another level. It needed two function pointers, f and del, because...

Example: f was needed to create the new content for each new list node, but if an allocation failed mid-way, I needed the del function to properly free the content of all the nodes I had already created for the new list. It was the ultimate test of leak-proof design.


4. Building a Real Project

This wasn't just a collection of .c files. It's a library.

My fourth Big Moment of realisation: Understanding the Makefile

Makefile Compilation Flow:

┌──────────┐     ┌──────────┐     ┌──────────┐
│  *.c     │ --> │ %.o: %.c │ --> │  *.o     │
│  files   │     │  (rule)  │     │  files   │
└──────────┘     └──────────┘     └──────────┘
                                        │
                                        v
                                  ┌──────────┐
                                  │ ar rcs   │
                                  │ command  │
                                  └──────────┘
                                        │
                                        v
                                  ┌──────────┐
                                  │ libft.a  │
                                  │ (archive)│
                                  └──────────┘

What each step does:

  • %.o: %.c rule: Pattern rule that teaches make how to compile any .c file into an object (.o) file
  • $(NAME): $(OBJS) rule: Gathers all those .o files
  • ar rcs $(NAME) $(OBJS): Builds the static library (.a file = "archive") from all object files

How to Use

Step 1: Clone the repository

git clone https://github.com/your-username/your-repo-name.git
cd your-repo-name

Step 2: Compile the library

make

This will create the libft.a file.

Step 3: Use it in your own C project

When compiling your project, you need to tell the compiler where to find the library (-L.) and which library to link (-lft).

Your project file (e.g., main.c):

#include "libft.h"

int main(void)
{
    ft_putendl_fd("My Libft works!", 1);
    return (0);
}

Compile your project:

cc -Wall -Wextra -Werror main.c -L. -lft -o my_program

✨ My Favorite Function: ft_split

This function is my favorite because it's a perfect example of what libft teaches.

static char **ft_memfree(char **strs, int l_arr)
{
    // THE MOST IMPORTANT PART!
    int i = 0;
    
    while (i < l_arr)
    {
        free(strs[i]); // Frees each individual word
        i++;
    }
    free(strs); // Frees the main array
    return (NULL);
}

char **ft_split(char const *s, char c)
{
    // ... main logic ...
    
    // Inside the fill_word loop:
    *arr = ft_word_dup(s, start, end);
    if (*arr == NULL)
        return (ft_memfree(strs, i)); // <-- This is beautiful.
    
    // ...
}

Why this matters:

The logic to handle a malloc failure inside the loop is the definition of robust C programming. It ensures that the function will not leak memory, even if the system runs out of resources halfway through its execution.

Memory Allocation Flow in ft_split:

Allocate main array (char**)
    │
    ├─> Allocate word 1 (char*) ✓
    ├─> Allocate word 2 (char*) ✓
    ├─> Allocate word 3 (char*) ✗ FAILS!
    │
    └─> ft_memfree is called:
        ├─> Free word 1
        ├─> Free word 2
        └─> Free main array
        
Result: ZERO memory leaks!

What I Learned

  • Memory is treacherous: Understanding pointers, allocation, and deallocation is critical
  • Security matters: Overflow checks and proper bounds checking prevent vulnerabilities
  • Robust code handles failure: Always assume malloc can fail and handle it gracefully
  • Function pointers unlock power: They enable flexible, reusable code patterns
  • Build systems matter: A proper Makefile makes your code a real, usable library

Built with dedication to understanding the fundamentals of C