A custom implementation of the C standard library's printf function, supporting a subset of format specifiers with proper flag and width handling.
ft_printf is a faithful recreation of the standard printf function, parsing format strings and converting arguments according to specified format codes. This project demonstrates deep understanding of:
- Variable argument handling (
va_list) - String parsing and tokenization
- Format flag and width parsing
- Number base conversion (decimal, hexadecimal, octal)
- Memory and output management
%c— Character%s— String%d/%i— Signed decimal integer%u— Unsigned decimal integer%x— Lowercase hexadecimal%X— Uppercase hexadecimal%p— Pointer address (hex with0xprefix)%%— Literal percent sign
-— Left-align output (default: right-align)0— Pad with zeros (default: pad with spaces)+— Always show sign for signed integers(space) — Show space for positive integers#— Alternative form (0x/0X for hex, leading 0 for octal)
- Width specifier:
%5d(minimum field width) - Precision specifier:
%.3f(applies to strings and floats) - Dynamic width/precision:
%*dand%.*s(from arguments)
ft_printf/
├── Makefile # Build rules
├── ft_printf.h # Header file with struct and function declarations
├── ft_printf.c # Main printf function and dispatcher
├── parse.c # Format string parsing (flags, width, precision)
├── ft_print_*.c # Individual format specifier handlers
│ ├── ft_print_char.c # %c handler
│ ├── ft_print_string.c # %s handler
│ ├── ft_print_int.c # %d/%i handler
│ ├── ft_print_unsigned.c # %u handler
│ ├── ft_print_hex.c # %x/%X handler
│ └── ft_print_pointer.c # %p handler
├── utils_*.c # Utility functions
│ ├── utils_chars.c # Character utilities (putchar)
│ ├── utils_numlen.c # Number length calculations
│ └── utils_putnbr.c # Number-to-string conversion
├── libft/ # Linked libft library (string/memory utilities)
└── testing/ # Test files
makemake bonusmake cleanmake fcleanmake re#include "ft_printf.h"gcc -L. -lftprintf -L./libft -lft main.c -o program#include "ft_printf.h"
int main(void)
{
ft_printf("Hello, %s!\n", "world");
ft_printf("Number: %d, Hex: %x\n", 42, 42);
ft_printf("Pointer: %p\n", (void *)&main);
return (0);
}- Flag parsing — Extract flags (
-,0,+,,#) - Width parsing — Read field width (or
*for dynamic) - Precision parsing — Read precision after
.(or*for dynamic) - Specifier parsing — Identify conversion character
typedef struct s_fmt
{
int minus; // -flag
int zero; // 0 flag
int plus; // + flag
int space; // space flag
int hash; // # flag
int width; // field width
int precision; // decimal precision
int dot; // precision specified
char spec; // conversion specifier
} t_fmt;- Format string is scanned character by character
- When
%is encountered, flags/width/precision are parsed - The appropriate handler function is called based on specifier
- Handler function formats and writes output
- Total characters printed is tracked and returned
The testing/ directory contains test files to verify correctness:
cd ft_printf
make
# Run your test suite hereCommon test cases:
- Basic specifiers:
%c,%s,%d,%x - Flag combinations:
%-10d,%+d,%010d - Width variations:
%5d,%*d - Precision:
%.3f,%.*s - Edge cases: NULL pointers, zero width, negative numbers
All code adheres to the 42 school norm:
- Maximum line length: 80 characters
- Consistent indentation (tabs)
- Function documentation and organization
- No trailing whitespace
Verify compliance:
norminette .- No memory leaks (verified with valgrind)
- Efficient buffer handling
- Proper cleanup of va_list usage
- acaldeir — 42 Lisboa student
- Created: 2025-11-03
- Updated: 2025-11-14
This project is part of the 42 curriculum. Educational use only.
- This implementation prioritizes correctness and code clarity over performance
- Not suitable for production use; use standard
printfinstead - Some advanced format specifiers (floats, scientific notation) are not implemented
- The codebase demonstrates best practices in C: modular design, clear naming, proper error handling