AgentSkillsCN

42-patterns

42-patterns

SKILL.md

42 Project Patterns Skill

Purpose

Apply common patterns, structures, and best practices for 42 School projects.

When to Use

  • Starting a new 42 project
  • Structuring code files
  • Creating Makefiles
  • Setting up project architecture
  • When user asks about "42 patterns", "project structure", or "42 best practices"

Standard Project Structure

code
project_name/
├── Makefile
├── README.md
├── subject/              # Project subject (PDF)
├── include/
│   └── project_name.h    # Main header file
├── src/                  # Source files
│   ├── main.c
│   ├── init.c
│   ├── utils.c
│   └── ...
├── obj/                  # Object files (gitignored)
└── bonus/               # Bonus part (if applicable)
    ├── src_bonus/
    └── include_bonus/

Standard Header Template

c
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   filename.c                                         :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: username <username@student.42.fr>          +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: YYYY/MM/DD HH:MM:SS by username         #+#    #+#             */
/*   Updated: YYYY/MM/DD HH:MM:SS by username        ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

Standard Makefile Pattern

makefile
# Program name
NAME = program_name

# Colors for output
GREEN = \033[0;32m
RED = \033[0;31m
RESET = \033[0m

# Directories
SRC_DIR = src
INCLUDE_DIR = include
OBJ_DIR = obj

# Compiler and flags
CC = cc
CFLAGS = -Wall -Wextra -Werror -I $(INCLUDE_DIR)
RM = rm -rf

# Source files
SRC = main.c \
      init.c \
      utils.c

OBJS = $(addprefix $(OBJ_DIR)/, $(SRC:.c=.o))

# Main target
all: $(NAME)

# Compile program
$(NAME): $(OBJS)
	@$(CC) $(CFLAGS) $(OBJS) -o $(NAME)
	@echo "$(GREEN)✓ $(NAME) compiled successfully!$(RESET)"

# Compile object files
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(OBJ_DIR)
	@$(CC) $(CFLAGS) -c $< -o $@
	@echo "$(GREEN)✓ Compiled: $<$(RESET)"

# Clean object files
clean:
	@$(RM) $(OBJ_DIR)
	@echo "$(RED)✗ Object files removed$(RESET)"

# Clean everything
fclean: clean
	@$(RM) $(NAME)
	@echo "$(RED)✗ $(NAME) removed$(RESET)"

# Rebuild
re: fclean all

.PHONY: all clean fclean re

Error Handling Pattern

Error Enum

c
typedef enum e_error
{
    ERR_ARGS = 1,
    ERR_MALLOC,
    ERR_INVALID_INPUT,
    ERR_SYSCALL
}   t_error;

Error Functions

c
// Exit with error message
void    error_exit(char *msg, int code)
{
    write(2, "Error: ", 7);
    write(2, msg, ft_strlen(msg));
    write(2, "\n", 1);
    exit(code);
}

// Return error code
int error_return(char *msg, int code)
{
    write(2, "Error: ", 7);
    write(2, msg, ft_strlen(msg));
    write(2, "\n", 1);
    return (code);
}

Initialization Pattern

c
// Always initialize variables
int     init_data(t_data *data)
{
    data->value = 0;
    data->ptr = NULL;
    data->flag = false;
    
    // Allocate memory with check
    data->array = malloc(sizeof(int) * size);
    if (!data->array)
        return (error_return("malloc failed", ERR_MALLOC));
    
    return (0);
}

Cleanup Pattern

c
void    cleanup_data(t_data *data)
{
    if (data->array)
        free(data->array);
    if (data->ptr)
        free(data->ptr);
    // Set to NULL after freeing
    data->array = NULL;
    data->ptr = NULL;
}

Parsing Pattern

c
// Validate arguments first
int validate_args(int ac, char **av)
{
    int i;
    
    if (ac < MIN_ARGS || ac > MAX_ARGS)
        return (error_return("invalid argument count", ERR_ARGS));
    
    i = 1;
    while (i < ac)
    {
        if (!is_valid_number(av[i]))
            return (error_return("invalid number format", ERR_ARGS));
        i++;
    }
    return (0);
}

// Then parse
int parse_args(t_data *data, int ac, char **av)
{
    data->arg1 = ft_atoi(av[1]);
    data->arg2 = ft_atoi(av[2]);
    // ... more parsing
    return (0);
}

Threading Pattern (for concurrent projects)

c
// Create threads
pthread_t   thread;

if (pthread_create(&thread, NULL, routine, data))
    return (error_return("thread creation failed", ERR_THREAD));

// Join threads
if (pthread_join(thread, NULL))
    return (error_return("thread join failed", ERR_THREAD));

// Mutex initialization
pthread_mutex_t mutex;

if (pthread_mutex_init(&mutex, NULL))
    return (error_return("mutex init failed", ERR_MUTEX));

// Always destroy mutexes
pthread_mutex_destroy(&mutex);

Main Function Pattern

c
int main(int ac, char **av)
{
    t_data  data;
    
    // 1. Validate input
    if (validate_args(ac, av))
        return (ERR_ARGS);
    
    // 2. Parse arguments
    if (parse_args(&data, ac, av))
        return (ERR_ARGS);
    
    // 3. Initialize
    if (init_data(&data))
        return (ERR_INIT);
    
    // 4. Execute main logic
    run_program(&data);
    
    // 5. Cleanup
    cleanup_data(&data);
    
    return (0);
}

.gitignore Pattern

code
# Object files
*.o
obj/
*.a

# Executables
program_name
*.out

# System files
.DS_Store
.vscode/
*.swp
*.swo
*~

# Test files
test
test.c
a.out

Best Practices

Memory Management

  • Always free what you malloc
  • Check malloc return values
  • Set pointers to NULL after freeing
  • Use valgrind to check leaks: valgrind --leak-check=full ./program

Code Organization

  • One function = one task
  • Keep functions under 25 lines
  • Group related functions in same file
  • Use static for helper functions
  • Clear, descriptive function names

Header Files

  • Include guards on all headers
  • Only function prototypes, no implementations
  • Group related declarations
  • Include necessary system headers

Testing

  • Test edge cases (0, negative, INT_MAX, etc.)
  • Test with various input combinations
  • Use fsanitize: cc -fsanitize=address -g
  • Check for race conditions (threading projects)

Documentation

  • Clear README with compilation and usage
  • Comment complex logic
  • Describe non-obvious algorithms
  • Keep guides folder with explanations