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:
Raphaël 2025-09-19 17:03:16 +02:00 committed by GitHub
commit 3ad528e353
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 600 additions and 309 deletions

13
.github/workflows/c-cpp.yml vendored Normal file
View 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
View 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
View 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
View file

@ -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}

View file

@ -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
View 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
View 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

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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
View 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
View 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
View 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
View 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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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));
}