ft_printf — Patch Notes (v2.0)
## ✨ New Features - **Custom `ft_printf`**: Complete implementation with variadic handling and standard format specifiers. - **Output Modules**: - `print_char.c` — single char writes - `print_number.c` — signed/unsigned, hex, pointer handling - `utils.c` — `itoa_base`, `ft_strlen`, and helpers - **Public Header**: `includes/ft_printf.h` exposes prototypes and shared types. --- ## ⚙️ Build & Tooling Upgrades - **Modernized `Makefile`** - Clean variable management, per-dir object builds, colored logs - Handy targets for dev/clean/rebuild and `.clangd` support - **Reproducible Dev Env**: `flake.nix` adds Nix flake support (clang, norminette, formatter, etc.) for one-command onboarding. 🧊 --- ## 🤖 Continuous Integration - **GitHub Actions**: - `c-cpp.yml` — builds on push/PR - `norminette.yml` — style checks to keep 42-compliant - Automatic gates so broken builds and non-conforming code don’t land. 🧪 --- ## 🧹 Cleanup & Refactors - **Redundant libft bits removed** (now provided internally by `ft_printf` utils): - `ft_strdup.c`, `ft_strlcpy.c`, `ft_strlen.c` - **README refresh**: trimmed outdated content; clearer scope and usage. --- ## 🧨 Breaking Changes - Projects previously including `libft`’s removed functions must now rely on the local utils bundled with `ft_printf` (or provide their own). - Include path is now **`includes/`**; verify your compiler flags (`-Iincludes`). --- ## 🧰 Usage Quickstart ```c #include "ft_printf.h" int main(void) { int n = ft_printf("Hello %s, number: %d, hex: 0x%x, ptr: %p\n", "world", 42, 42, (void*)&n); ft_printf("Printed %d bytes above.\n", n); return 0; }
This commit is contained in:
commit
3ad528e353
17 changed files with 600 additions and 309 deletions
13
.github/workflows/c-cpp.yml
vendored
Normal file
13
.github/workflows/c-cpp.yml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
name: C/C++ CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make
|
||||||
|
run: TERM=xterm make
|
||||||
10
.github/workflows/norminette.yml
vendored
Normal file
10
.github/workflows/norminette.yml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
norminette_job:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: norminette
|
||||||
|
steps:
|
||||||
|
- uses: alexandregv/norminette-action@v3
|
||||||
|
with:
|
||||||
|
flags: '.'
|
||||||
61
.gitignore
vendored
Normal file
61
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
to_do*
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
build/
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
.test/
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
.clangd
|
||||||
|
|
||||||
|
# Nix files
|
||||||
|
*.lock
|
||||||
|
.envrc
|
||||||
|
.direnv/
|
||||||
152
Makefile
152
Makefile
|
|
@ -3,64 +3,132 @@
|
||||||
# ::: :::::::: #
|
# ::: :::::::: #
|
||||||
# Makefile :+: :+: :+: #
|
# Makefile :+: :+: :+: #
|
||||||
# +:+ +:+ +:+ #
|
# +:+ +:+ +:+ #
|
||||||
# By: rparodi <marvin@42.fr> +#+ +:+ +#+ #
|
# By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/11/12 11:05:05 by rparodi #+# #+# #
|
# Created: 2025/09/18 17:28:18 by rparodi #+# #+# #
|
||||||
# Updated: 2023/12/27 18:35:14 by raphael ### ########.fr #
|
# Updated: 2025/09/19 16:07:44 by rparodi ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
NAME=libftprintf.a
|
# Variables
|
||||||
CC=clang
|
|
||||||
CFLAGS=-Wall -Wextra -Werror
|
|
||||||
RM=rm -f
|
|
||||||
LIBFT = ./libft/ft_strdup.c ./libft/ft_strlcpy.c ./libft/ft_strlen.c
|
|
||||||
SRC = ./src/ft_printf.c ./src/ft_put.c
|
|
||||||
OBJ = $(SRC:.c=.o)
|
|
||||||
OBJLibft = $(LIBFT:.c=.o)
|
|
||||||
|
|
||||||
|
# Name
|
||||||
|
NAME = libftprintf.a
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
CC ?= clang
|
||||||
|
RM = rm -rf
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
CFLAGS = -Werror -Wextra -Wall
|
||||||
|
# CFLAGS += -g
|
||||||
|
|
||||||
|
INC_DIR = includes
|
||||||
|
CPPFLAGS = $(addprefix -I, $(INC_DIR)) -MMD -MP
|
||||||
|
|
||||||
|
|
||||||
|
# Objects
|
||||||
|
OBJDIRNAME = ./build
|
||||||
|
OBJ = $(addprefix $(OBJDIRNAME)/,$(SRC:.c=.o))
|
||||||
|
|
||||||
|
SRC = sources/print_char.c \
|
||||||
|
sources/utils.c \
|
||||||
|
sources/print_number.c \
|
||||||
|
sources/ft_printf.c
|
||||||
|
|
||||||
|
# Colors
|
||||||
GREEN = \033[32m
|
GREEN = \033[32m
|
||||||
GREY = \033[0;90m
|
GREY = \033[0;90m
|
||||||
RED = \033[0;31m
|
RED = \033[0;31m
|
||||||
GOLD = \033[38;5;220m
|
GOLD = \033[38;5;220m
|
||||||
END = \033[0m
|
END = \033[0m
|
||||||
|
|
||||||
all: header $(NAME)
|
# Rules
|
||||||
@printf '\n$(GREY) Compilation $(GREEN)Done\n'
|
|
||||||
|
|
||||||
header:
|
# All (make all)
|
||||||
@printf '\n\n'
|
all: header $(NAME) footer
|
||||||
@printf '$(GOLD) ******* ***** ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ****** *** ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ******* ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ****** ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ******* ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ******************** ******* * $(END)\n'
|
|
||||||
@printf '$(GOLD) ******************** ******* *** $(END)\n'
|
|
||||||
@printf '$(GOLD) ******* ******* ****** $(END)\n'
|
|
||||||
@printf '$(GOLD) ******* $(END)\n'
|
|
||||||
@printf '$(GOLD) ******* $(END)\n\n'
|
|
||||||
@printf '$(GREY) Made by rparodi$(END)\n\n\n'
|
|
||||||
|
|
||||||
$(NAME): $(OBJ) $(OBJLibft)
|
# Bonus (make bonus)
|
||||||
@printf '$(GREY) Compiling $(END)$(GOLD)$(NAME)$(END)\n'
|
bonus: header $(OBJ) $(LIB_OBJ) footer
|
||||||
@ar rc $(NAME) $(OBJ) $(OBJLibft)
|
@mkdir -p $(OBJDIRNAME)
|
||||||
@ranlib $(NAME)
|
@mkdir -p $(OBJDIRNAME)/$(SRCDIRNAME)
|
||||||
|
@printf '$(GREY) Be Carefull ur in $(END)$(GREEN)Debug Mode$(END)\n'
|
||||||
%.o: %.c
|
@$(CC) $(CFLAGS) $(CPPFLAGS) -D BONUS=1 -o $(NAME) $(OBJ) $(LIB_OBJ)
|
||||||
@printf '$(GREY) Compiling $(END)$(GREEN)$<$(END)\n'
|
|
||||||
@$(CC) -I. -o $@ -c $? $(CFLAGS)
|
|
||||||
|
|
||||||
dev: all bonus clean
|
|
||||||
|
|
||||||
|
# Clean (make clean)
|
||||||
clean:
|
clean:
|
||||||
@printf '$(GREY) Removing $(END)$(RED)Object$(END)\n'
|
@printf '$(GREY) Removing $(END)$(RED)Objects$(END)\n'
|
||||||
@$(RM) $(OBJ) $(OBJLibft)
|
@printf '$(GREY) Removing $(END)$(RED)Objects Folder$(END)\n'
|
||||||
|
@$(RM) $(OBJDIRNAME)
|
||||||
|
|
||||||
|
# Clean (make fclean)
|
||||||
fclean: clean
|
fclean: clean
|
||||||
@printf '$(GREY) Removing $(END)$(RED)Program$(END)\n'
|
@printf '$(GREY) Removing $(END)$(RED)Program$(END)\n'
|
||||||
@$(RM) $(NAME)
|
@$(RM) $(NAME)
|
||||||
|
@$(RM) ./.test/
|
||||||
|
@echo ""
|
||||||
|
|
||||||
re: fclean all
|
# Restart (make re)
|
||||||
|
re: header fclean all
|
||||||
|
|
||||||
.PHONY: all bonus clean fclean re dev header
|
# Dependences for all
|
||||||
|
$(NAME): $(OBJ)
|
||||||
|
@mkdir -p $(OBJDIRNAME)
|
||||||
|
@ar rc $(NAME) $(OBJ)
|
||||||
|
@ranlib $(NAME)
|
||||||
|
|
||||||
|
# Creating the objects
|
||||||
|
$(OBJDIRNAME)/%.o: %.c
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
@printf '$(GREY) Compiling $(END)$(GREEN)$<$(END)\n'
|
||||||
|
@$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
# Header
|
||||||
|
header:
|
||||||
|
@clear
|
||||||
|
@printf '\n\n'
|
||||||
|
@printf '$(GOLD) ******* ****** ******* $(END)\n'
|
||||||
|
@printf '$(GOLD) ****** *** ******* $(END)\n'
|
||||||
|
@printf '$(GOLD) ******* * ******* $(END)\n'
|
||||||
|
@printf '$(GOLD) ****** ******* $(END)\n'
|
||||||
|
@printf '$(GOLD) ******* ******* $(END)\n'
|
||||||
|
@printf '$(GOLD) ******************* ******* * $(END)\n'
|
||||||
|
@printf '$(GOLD) ******************* ******* *** $(END)\n'
|
||||||
|
@printf '$(GOLD) ****** ******* ****** $(END)\n'
|
||||||
|
@printf '$(GOLD) ****** $(END)\n'
|
||||||
|
@printf '$(GOLD) ****** $(END)\n'
|
||||||
|
@printf '$(GREY) Made by rparodi$(END)\n\n'
|
||||||
|
|
||||||
|
# Footer
|
||||||
|
footer:
|
||||||
|
@printf "\n"
|
||||||
|
@printf "$(GOLD) ,_ _,$(END)\n"
|
||||||
|
@printf "$(GOLD) | \\___//|$(END)\n"
|
||||||
|
@printf "$(GOLD) |=6 6=|$(END)\n"
|
||||||
|
@printf "$(GOLD) \\=._Y_.=/$(END)\n"
|
||||||
|
@printf "$(GOLD) ) \` ( ,$(END)\n"
|
||||||
|
@printf "$(GOLD) / \\ (('$(END)\n"
|
||||||
|
@printf "$(GOLD) | | ))$(END)\n"
|
||||||
|
@printf "$(GOLD) /| | | |\\_//$(END)\n"
|
||||||
|
@printf "$(GOLD) \\| |._.| |/-\`$(END)\n"
|
||||||
|
@printf "$(GOLD) '\"' '\"'$(END)\n"
|
||||||
|
@printf ' $(GREY)The compilation is$(END) $(GOLD)finished$(END)\n $(GREY)Have a good $(END)$(GOLD)correction !$(END)\n'
|
||||||
|
|
||||||
|
clangd:
|
||||||
|
@printf "CompileFlags:\n" > ./.clangd
|
||||||
|
@printf " Add:\n" >> ./.clangd
|
||||||
|
@printf " - \"-xc\"\n" >> ./.clangd
|
||||||
|
@for FLAG in $(CXXFLAGS); do \
|
||||||
|
printf " - \"$$FLAG\"\n" >> ./.clangd; \
|
||||||
|
done
|
||||||
|
@printf " - \"-I"$(shell pwd)"/\"\n" >> .clangd;
|
||||||
|
@for file in $(INC_DIR); do \
|
||||||
|
printf " - \"-I"$(shell pwd)"/"$$file"\"\n" >> .clangd; \
|
||||||
|
done
|
||||||
|
@printf "\n" >> ./.clangd
|
||||||
|
@printf '$(GREY) Now parsing settings is set in $(END)$(GREEN)./.clangd$(END)\n'
|
||||||
|
|
||||||
|
# Phony
|
||||||
|
.PHONY: all bonus clean fclean re footer header clangd
|
||||||
|
|
||||||
|
-include ${OBJ:.o=.d}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
This project is pretty straightforward, you have to recode printf. You will learn what is and how to implement variadic functions. Once you validate it, you will reuse this function in your future projects.
|
|
||||||
##
|
|
||||||
| Keywords | Skills |
|
|
||||||
| ------|-----|
|
|
||||||
| Unix Logic | Algorithms & AI |
|
|
||||||
|| Rigor |
|
|
||||||
28
flake.nix
Normal file
28
flake.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
description = "Flake for 42 C";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
c_formatter_42.url = "github:maix-flake/c_formatter_42";
|
||||||
|
};
|
||||||
|
outputs = { self, nixpkgs, flake-utils, c_formatter_42 }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in {
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
c_formatter_42.packages.${system}.default
|
||||||
|
pkgs.clang
|
||||||
|
pkgs.clang-tools
|
||||||
|
pkgs.lldb
|
||||||
|
pkgs.fastmod
|
||||||
|
pkgs.norminette
|
||||||
|
pkgs.tree
|
||||||
|
] ++ (if pkgs.stdenv.isLinux then [ pkgs.valgrind ] else [ ]);
|
||||||
|
};
|
||||||
|
shellHook = ''
|
||||||
|
export CC=${pkgs.clang}
|
||||||
|
printf "\n\033[0;90mC env loaded for: \033[38;5;220m${system}\033[0m\n"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
}
|
||||||
42
includes/ft_printf.h
Normal file
42
includes/ft_printf.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* ft_printf.h :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/17 17:42:12 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2025/09/19 15:53:37 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#ifndef FT_PRINTF_H
|
||||||
|
# define FT_PRINTF_H
|
||||||
|
|
||||||
|
# include <stdarg.h>
|
||||||
|
# include <stddef.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef int (*t_func)(va_list, int fd);
|
||||||
|
|
||||||
|
typedef struct s_format
|
||||||
|
{
|
||||||
|
char character;
|
||||||
|
t_func function;
|
||||||
|
} t_format;
|
||||||
|
|
||||||
|
size_t ft_strlen(const char *str);
|
||||||
|
void ft_putnbr_base(int fd, uint64_t nbr, char *base, int *to_ret);
|
||||||
|
char *itoa_base(uint64_t nbr, char *base);
|
||||||
|
int flag_c(va_list args, int fd);
|
||||||
|
int ft_dprintf(int fd, const char *s, ...);
|
||||||
|
int ft_printf(const char *s, ...);
|
||||||
|
int flag_i(va_list args, int fd);
|
||||||
|
int flag_p(va_list args, int fd);
|
||||||
|
int flag_percent(va_list args, int fd);
|
||||||
|
int flag_s(va_list args, int fd);
|
||||||
|
int flag_u(va_list args, int fd);
|
||||||
|
int flag_x(va_list args, int fd);
|
||||||
|
int flag_x_maj(va_list args, int fd);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_strdup.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/07 16:53:59 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/11/16 15:12:05 by rparodi ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "../src/ft_printf.h"
|
|
||||||
|
|
||||||
char *ft_strdup(const char *s)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
char *to_return;
|
|
||||||
|
|
||||||
len = ft_strlen(s) + 1;
|
|
||||||
to_return = (char *)malloc(sizeof(char) * len);
|
|
||||||
if (!to_return)
|
|
||||||
return (NULL);
|
|
||||||
ft_strlcpy(to_return, s, len);
|
|
||||||
return (to_return);
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_strlcpy.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/07 16:55:25 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/11/16 15:12:05 by rparodi ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "../src/ft_printf.h"
|
|
||||||
|
|
||||||
size_t ft_strlcpy(char *dst, const char *src, size_t size)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (src[i] && i + 1 < size)
|
|
||||||
{
|
|
||||||
dst[i] = src[i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
dst[i] = '\0';
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (ft_strlen(src));
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_strlen.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/07 16:56:24 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/11/16 15:11:46 by rparodi ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "../src/ft_printf.h"
|
|
||||||
|
|
||||||
size_t ft_strlen(const char *s)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (s[i] != '\0')
|
|
||||||
i++;
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
97
sources/ft_printf.c
Normal file
97
sources/ft_printf.c
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* ft_printf.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/17 17:44:34 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2025/09/19 15:35:38 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "ft_printf.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int print_buff(int fd, const char *s, size_t start, size_t end)
|
||||||
|
{
|
||||||
|
return (write(fd, s + start, (end - start)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_managenent(int fd, char flag, va_list args)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
const t_format flags[] = {
|
||||||
|
{'c', flag_c},
|
||||||
|
{'d', flag_i},
|
||||||
|
{'p', flag_p},
|
||||||
|
{'u', flag_u},
|
||||||
|
{'%', flag_percent},
|
||||||
|
{'i', flag_i},
|
||||||
|
{'s', flag_s},
|
||||||
|
{'x', flag_x},
|
||||||
|
{'X', flag_x_maj},
|
||||||
|
};
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (flags[i].character)
|
||||||
|
{
|
||||||
|
if (flags[i].character == flag)
|
||||||
|
return (flags[i].function(args, fd));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_vdprintf(int fd, const char *s, va_list args)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t temp;
|
||||||
|
int to_ret;
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return (-1);
|
||||||
|
i = 0;
|
||||||
|
to_ret = 0;
|
||||||
|
temp = 0;
|
||||||
|
while (s[i])
|
||||||
|
{
|
||||||
|
if (s[i] == '%')
|
||||||
|
{
|
||||||
|
to_ret += print_buff(fd, s, temp, i);
|
||||||
|
if (s[++i])
|
||||||
|
to_ret += flag_managenent(fd, s[i], args);
|
||||||
|
else
|
||||||
|
return (write(1, &s[i - 1], 1) + to_ret);
|
||||||
|
temp = i + 1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
to_ret += print_buff(fd, s, temp, i);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_dprintf(int fd, const char *s, ...)
|
||||||
|
{
|
||||||
|
int to_ret;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, s);
|
||||||
|
to_ret = ft_vdprintf(fd, s, args);
|
||||||
|
va_end(args);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_printf(const char *s, ...)
|
||||||
|
{
|
||||||
|
int to_ret;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, s);
|
||||||
|
to_ret = ft_vdprintf(1, s, args);
|
||||||
|
va_end(args);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
39
sources/print_char.c
Normal file
39
sources/print_char.c
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* print_char.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/18 14:49:02 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2025/09/19 15:39:41 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "ft_printf.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int flag_c(va_list args, int fd)
|
||||||
|
{
|
||||||
|
const char character = va_arg(args, int);
|
||||||
|
|
||||||
|
return (write(fd, &character, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_s(va_list args, int fd)
|
||||||
|
{
|
||||||
|
const char *string = va_arg(args, char *);
|
||||||
|
|
||||||
|
if (string == NULL)
|
||||||
|
return (write(fd, "(null)", 6));
|
||||||
|
return (write(fd, string, ft_strlen(string)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_percent(va_list args, int fd)
|
||||||
|
{
|
||||||
|
(void)args;
|
||||||
|
return (write(fd, "%", 1));
|
||||||
|
}
|
||||||
96
sources/print_number.c
Normal file
96
sources/print_number.c
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* print_number.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/18 15:00:27 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2025/09/19 16:06:27 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "ft_printf.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int flag_p(va_list args, int fd)
|
||||||
|
{
|
||||||
|
char *to_print;
|
||||||
|
int to_ret;
|
||||||
|
uint64_t number;
|
||||||
|
|
||||||
|
number = va_arg(args, unsigned long long);
|
||||||
|
to_ret = 0;
|
||||||
|
if (number != 0)
|
||||||
|
to_ret += write(fd, "0x", 2);
|
||||||
|
else if (number == 0)
|
||||||
|
return (write(fd, "(nil)", 5));
|
||||||
|
to_print = itoa_base(number, "0123456789abcdef");
|
||||||
|
to_ret += write(fd, to_print, ft_strlen(to_print));
|
||||||
|
free(to_print);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_x_maj(va_list args, int fd)
|
||||||
|
{
|
||||||
|
char *to_print;
|
||||||
|
int to_ret;
|
||||||
|
unsigned int number;
|
||||||
|
|
||||||
|
number = va_arg(args, unsigned int);
|
||||||
|
to_print = itoa_base(number, "0123456789ABCDEF");
|
||||||
|
to_ret = write(fd, to_print, ft_strlen(to_print));
|
||||||
|
free(to_print);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_x(va_list args, int fd)
|
||||||
|
{
|
||||||
|
char *to_print;
|
||||||
|
int to_ret;
|
||||||
|
unsigned int number;
|
||||||
|
|
||||||
|
number = va_arg(args, unsigned int);
|
||||||
|
to_print = itoa_base(number, "0123456789abcdef");
|
||||||
|
to_ret = write(fd, to_print, ft_strlen(to_print));
|
||||||
|
free(to_print);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_u(va_list args, int fd)
|
||||||
|
{
|
||||||
|
char *to_print;
|
||||||
|
int to_ret;
|
||||||
|
unsigned int number;
|
||||||
|
|
||||||
|
to_ret = 0;
|
||||||
|
number = va_arg(args, unsigned int);
|
||||||
|
to_print = itoa_base(number, "0123456789");
|
||||||
|
to_ret = write(fd, to_print, ft_strlen(to_print));
|
||||||
|
free(to_print);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flag_i(va_list args, int fd)
|
||||||
|
{
|
||||||
|
char *to_print;
|
||||||
|
int number;
|
||||||
|
int to_ret;
|
||||||
|
|
||||||
|
to_ret = 0;
|
||||||
|
number = va_arg(args, int);
|
||||||
|
if (number < 0)
|
||||||
|
{
|
||||||
|
if (number == INT_MIN)
|
||||||
|
return (write(1, "-2147483648", 11));
|
||||||
|
number = -number;
|
||||||
|
to_ret += write(1, "-", 1);
|
||||||
|
}
|
||||||
|
to_print = itoa_base(number, "0123456789");
|
||||||
|
to_ret += write(fd, to_print, ft_strlen(to_print));
|
||||||
|
free(to_print);
|
||||||
|
return (to_ret);
|
||||||
|
}
|
||||||
104
sources/utils.c
Normal file
104
sources/utils.c
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* utils.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: rparodi <rparodi@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/18 15:34:52 by rparodi #+# #+# */
|
||||||
|
/* Updated: 2025/09/19 16:52:30 by rparodi ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static size_t ft_nbrlen(uint64_t nbr, size_t base_len)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (nbr == 0)
|
||||||
|
return (1);
|
||||||
|
len = 0;
|
||||||
|
while (nbr > 0)
|
||||||
|
{
|
||||||
|
nbr /= base_len;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return (len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *ft_memset(void *s, int c, size_t n)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
str = (char *)s;
|
||||||
|
while (i < n)
|
||||||
|
{
|
||||||
|
str[i] = c;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ft_strlen(const char *str)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return (0);
|
||||||
|
i = 0;
|
||||||
|
while (str[i])
|
||||||
|
i++;
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ft_calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
size_t total;
|
||||||
|
char *to_return;
|
||||||
|
|
||||||
|
if (nmemb == 0 || size == 0)
|
||||||
|
return ((void *)malloc(1));
|
||||||
|
total = nmemb * size;
|
||||||
|
if (total / nmemb != size && total / size != nmemb)
|
||||||
|
return (NULL);
|
||||||
|
to_return = (char *)malloc(total);
|
||||||
|
if (to_return == NULL)
|
||||||
|
to_return = NULL;
|
||||||
|
else
|
||||||
|
ft_memset(to_return, 0, nmemb * size);
|
||||||
|
return (to_return);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *itoa_base(uint64_t nbr, char *base)
|
||||||
|
{
|
||||||
|
size_t base_len;
|
||||||
|
size_t nbr_len;
|
||||||
|
char *result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!base)
|
||||||
|
return (NULL);
|
||||||
|
base_len = ft_strlen(base);
|
||||||
|
if (base_len < 2)
|
||||||
|
return (NULL);
|
||||||
|
nbr_len = ft_nbrlen(nbr, base_len);
|
||||||
|
result = malloc(sizeof(char) * (nbr_len + 1));
|
||||||
|
if (!result)
|
||||||
|
return (NULL);
|
||||||
|
i = nbr_len - 1;
|
||||||
|
if (nbr == 0)
|
||||||
|
result[0] = base[0];
|
||||||
|
while (nbr > 0)
|
||||||
|
{
|
||||||
|
result[i] = base[nbr % base_len];
|
||||||
|
nbr /= base_len;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_printf.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/14 17:27:44 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/12/14 18:17:22 by raphael ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "ft_printf.h"
|
|
||||||
|
|
||||||
int ft_check_args(char c, va_list args, int *ret_value)
|
|
||||||
{
|
|
||||||
if (c == 'c')
|
|
||||||
ft_putchar((char)va_arg(args, int), ret_value);
|
|
||||||
else if (c == 's')
|
|
||||||
ft_putstr((char *)va_arg(args, char *), ret_value);
|
|
||||||
else if (c == 'i' || c == 'd')
|
|
||||||
ft_putnbr((int)va_arg(args, int), ret_value);
|
|
||||||
else if (c == '%')
|
|
||||||
ft_putchar('%', ret_value);
|
|
||||||
else if (c == 'u')
|
|
||||||
ft_putnbr_unsigned((unsigned int)va_arg(args, unsigned int), ret_value);
|
|
||||||
else if (c == 'x')
|
|
||||||
ft_putnbr_base((unsigned int)va_arg(args, unsigned int), \
|
|
||||||
"0123456789abcdef", ret_value, c);
|
|
||||||
else if (c == 'X')
|
|
||||||
ft_putnbr_base((unsigned int)va_arg(args, unsigned int), \
|
|
||||||
"0123456789ABCDEF", ret_value, c);
|
|
||||||
else if (c == 'p')
|
|
||||||
ft_putnbr_base((unsigned long long)va_arg(args, unsigned long long), \
|
|
||||||
"0123456789abcdef", ret_value, c);
|
|
||||||
va_end(args);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ft_printf(const char *s, ...)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
va_list args;
|
|
||||||
char *str;
|
|
||||||
int ret_value;
|
|
||||||
|
|
||||||
ret_value = 0;
|
|
||||||
str = ft_strdup(s);
|
|
||||||
va_start(args, s);
|
|
||||||
i = 0;
|
|
||||||
while (str[i])
|
|
||||||
{
|
|
||||||
if (str[i] == '%')
|
|
||||||
{
|
|
||||||
ft_check_args(str[i + 1], args, &ret_value);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ft_putchar(str[i], &ret_value);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
free(str);
|
|
||||||
return (ret_value);
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_printf.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/14 15:59:10 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/11/16 15:10:41 by rparodi ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef FT_PRINTF_H
|
|
||||||
# define FT_PRINTF_H
|
|
||||||
# include <stdlib.h>
|
|
||||||
# include <stdarg.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
|
|
||||||
# define UINT_MAX 4294967295
|
|
||||||
# define INT_MAX 2147483647
|
|
||||||
# define INT_MIN -2147483648
|
|
||||||
|
|
||||||
int ft_printf(const char *str, ...);
|
|
||||||
int ft_check_args(char c, va_list args, int *ret_value);
|
|
||||||
void ft_putnbr_unsigned(unsigned int nb, int *ret_value);
|
|
||||||
void ft_putnbr(int nb, int *ret_value);
|
|
||||||
void ft_putchar(char c, int *ret_value);
|
|
||||||
void ft_putstr(char *str, int *ret_value);
|
|
||||||
void ft_putnbr_base(\
|
|
||||||
unsigned long long nbr, char *base, int *ret_value, char c);
|
|
||||||
size_t ft_strlcpy(char *dst, const char *src, size_t size);
|
|
||||||
size_t ft_strlen(const char *s);
|
|
||||||
char *ft_strdup(const char *s);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
82
src/ft_put.c
82
src/ft_put.c
|
|
@ -1,82 +0,0 @@
|
||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* ft_put.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: rparodi <marvin@42.fr> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/16 12:13:14 by rparodi #+# #+# */
|
|
||||||
/* Updated: 2023/12/23 17:33:46 by raphael ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include "ft_printf.h"
|
|
||||||
|
|
||||||
void ft_putchar(char c, int *ret_value)
|
|
||||||
{
|
|
||||||
write(1, &c, 1);
|
|
||||||
(*ret_value)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ft_putnbr(int nb, int *ret_value)
|
|
||||||
{
|
|
||||||
if (nb < 0)
|
|
||||||
{
|
|
||||||
if (nb == INT_MIN)
|
|
||||||
{
|
|
||||||
write(1, "-2147483648", 11);
|
|
||||||
*ret_value += 11;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
nb = -nb;
|
|
||||||
ft_putchar('-', ret_value);
|
|
||||||
}
|
|
||||||
if (nb >= 10)
|
|
||||||
{
|
|
||||||
ft_putnbr(nb / 10, ret_value);
|
|
||||||
nb = nb % 10;
|
|
||||||
}
|
|
||||||
if (nb < 10)
|
|
||||||
ft_putchar(nb + 48, ret_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ft_putnbr_base(\
|
|
||||||
unsigned long long nbr, char *base, int *ret_value, char c)
|
|
||||||
{
|
|
||||||
if (c == 'p')
|
|
||||||
{
|
|
||||||
if (nbr != 0)
|
|
||||||
ft_putstr("0x", ret_value);
|
|
||||||
else if (nbr == 0)
|
|
||||||
{
|
|
||||||
ft_putstr("(nil)", ret_value);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
if (c != 'p')
|
|
||||||
{
|
|
||||||
if (nbr >= 16)
|
|
||||||
ft_putnbr_base(nbr / 16, base, ret_value, c);
|
|
||||||
ft_putchar(base[nbr % 16], ret_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ft_putnbr_unsigned(unsigned int nb, int *ret_value)
|
|
||||||
{
|
|
||||||
if (nb >= 10)
|
|
||||||
{
|
|
||||||
ft_putnbr_unsigned(nb / 10, ret_value);
|
|
||||||
nb = nb % 10;
|
|
||||||
}
|
|
||||||
if (nb < 10)
|
|
||||||
ft_putchar(nb + 48, ret_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ft_putstr(char *str, int *ret_value)
|
|
||||||
{
|
|
||||||
if (!str)
|
|
||||||
*ret_value += write(1, "(null)", 6);
|
|
||||||
else
|
|
||||||
*ret_value += write(1, str, ft_strlen(str));
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue