Merge mandatory and bonus into a single ft_printf, fix edge cases, add README

- Use the flag-aware implementation for both make and make bonus
  (bonus/ moved to src/, _bonus suffix dropped, bonus rule = all)
- Do not treat zero-length output (%s with "", %.0d with 0) as an error
- Return -1 without printing when a % has no conversion ("abc%", "%5")
- Keep field width with '#', '+' and ' '; ignore '0' with '-'
- Fix '#' prefix on zero, '+'/' ' with zero padding, INT_MIN negation UB
- Add README.md required by the subject

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
da7eandClaude Opus 5.5 committed 2026-10-08 22:22:28 +02:00
1 parent b620f5ecdb
commit c8a9ee10cf
24 files changed
+607 -677

No files matched your search

+8 -27
View File
@@ -1,9 +1,7 @@
NAME= libftprintf.a NAME= libftprintf.a
LIBFT= $(BUILD_DIR)/libft.a LIBFT= $(BUILD_DIR)/libft.a
BONUS= $(BUILD_DIR)/libftprintf_bonus.a
SRC_DIR= src SRC_DIR= src
B_SRC_DIR= bonus
INC_DIR= include INC_DIR= include
LIBFT_DIR= libft LIBFT_DIR= libft
BUILD_DIR= .build BUILD_DIR= .build
@@ -16,25 +14,13 @@ SRC= $(SRC_DIR)/ft_printf.c \
$(SRC_DIR)/print_pointer.c \ $(SRC_DIR)/print_pointer.c \
$(SRC_DIR)/print_str.c \ $(SRC_DIR)/print_str.c \
$(SRC_DIR)/print_unsigned.c \ $(SRC_DIR)/print_unsigned.c \
$(SRC_DIR)/ft_create_arg.c \
B_SRC= $(B_SRC_DIR)/ft_printf_bonus.c \ $(SRC_DIR)/ft_main_arg.c \
$(B_SRC_DIR)/ft_putnbr_base_bonus.c \ $(SRC_DIR)/ft_parsing.c \
$(B_SRC_DIR)/print_char_bonus.c \ $(SRC_DIR)/utils_flag.c
$(B_SRC_DIR)/print_hex_bonus.c \
$(B_SRC_DIR)/print_number_bonus.c \
$(B_SRC_DIR)/print_pointer_bonus.c \
$(B_SRC_DIR)/print_str_bonus.c \
$(B_SRC_DIR)/print_unsigned_bonus.c \
$(B_SRC_DIR)/ft_create_arg_bonus.c \
$(B_SRC_DIR)/ft_main_arg_bonus.c \
$(B_SRC_DIR)/ft_parsing_bonus.c \
$(B_SRC_DIR)/utils_flag_bonus.c
OBJ= $(SRC:%.c=$(BUILD_DIR)/%.o) OBJ= $(SRC:%.c=$(BUILD_DIR)/%.o)
B_OBJ= $(B_SRC:%.c=$(BUILD_DIR)/%.o)
DEP= $(SRC:%.c=$(BUILD_DIR)/%.d) DEP= $(SRC:%.c=$(BUILD_DIR)/%.d)
B_DEP= $(B_SRC:%.c=$(BUILD_DIR)/%.d)
CC= cc CC= cc
CFLAGS= -Wall -Wextra -Werror -I$(INC_DIR) -I$(LIBFT_DIR) -MMD -MP CFLAGS= -Wall -Wextra -Werror -I$(INC_DIR) -I$(LIBFT_DIR) -MMD -MP
@@ -42,8 +28,7 @@ AR= ar rcs
all: $(NAME) all: $(NAME)
bonus: $(BONUS) bonus: all
cp $(BONUS) $(NAME)
$(NAME): $(OBJ) $(LIBFT) $(NAME): $(OBJ) $(LIBFT)
cp $(LIBFT) $(NAME) cp $(LIBFT) $(NAME)
@@ -57,20 +42,16 @@ $(LIBFT):
$(MAKE) -C $(LIBFT_DIR) $(MAKE) -C $(LIBFT_DIR)
cp $(LIBFT_DIR)/libft.a $(LIBFT) cp $(LIBFT_DIR)/libft.a $(LIBFT)
$(BONUS): $(B_OBJ) $(LIBFT)
cp $(LIBFT) $(BONUS)
$(AR) $(BONUS) $(B_OBJ)
clean: clean:
rm -f $(OBJ) $(DEP) $(B_OBJ) $(B_DEP) rm -f $(OBJ) $(DEP)
$(MAKE) -C $(LIBFT_DIR) clean $(MAKE) -C $(LIBFT_DIR) clean
fclean: clean fclean: clean
rm -f $(NAME) $(BONUS) $(LIBFT) rm -f $(NAME) $(LIBFT)
$(MAKE) -C $(LIBFT_DIR) fclean $(MAKE) -C $(LIBFT_DIR) fclean
re: fclean all re: fclean all
-include $(DEP) $(B_DEP) -include $(DEP)
.PHONY: all clean fclean re bonus .PHONY: all clean fclean re bonus
+196
View File
@@ -0,0 +1,196 @@
*This project has been created as part of the 42 curriculum by dgaillet.*
# ft_printf
## Description
`ft_printf` is a reimplementation of the libc `printf()` function, packaged as a
static library (`libftprintf.a`). The goal of the project is to learn how
variadic functions work in C (`va_start`, `va_arg`, `va_end`) and to build
code that is easy to extend with new conversions and flags.
```c
int ft_printf(const char *format, ...);
```
It writes to standard output and returns the number of characters it printed.
It returns `-1` on a write error or an invalid format.
### Supported conversions (mandatory)
| Conversion | Output |
|---|---|
| `%c` | a single character |
| `%s` | a string (`(null)` for a `NULL` pointer) |
| `%p` | a pointer in hexadecimal, with a `0x` prefix (`(nil)` for `NULL`) |
| `%d` / `%i` | a signed decimal integer |
| `%u` | an unsigned decimal integer |
| `%x` / `%X` | an unsigned integer in lowercase / uppercase hexadecimal |
| `%%` | a literal `%` |
### Supported flags (bonus)
The same implementation handles both the mandatory conversions and the bonus
flags, so there is only one version of `ft_printf`.
- Minimum field width, for example `%10d`
- `-`: left-justify within the field
- `0`: pad numbers with zeros (ignored when `-` or a precision is given)
- `.`: precision (minimum digits for numbers, maximum characters for `%s`)
- `#`: `0x` / `0X` prefix for non-zero `%x` / `%X`
- `+`: always print a sign for signed numbers
- ` ` (space): print a space in front of positive signed numbers
Any combination of these flags behaves like glibc's `printf`.
## Instructions
### Compilation
```sh
make # builds libftprintf.a (conversions and flags)
make bonus # same as make: the bonus is built into the library
make clean # removes object files
make fclean # removes object files and libraries
make re # fclean + all
```
The `Makefile` first builds `libft` with its own `Makefile`, then adds the
`ft_printf` objects to a copy of `libft.a`. This way, `libftprintf.a`
contains everything it needs.
### Usage
```c
#include "ft_printf.h"
int main(void)
{
int len;
len = ft_printf("Hello %s, you are %d years old (%#x)\n", "Bob", 42, 42);
ft_printf("%d characters printed\n", len);
return (0);
}
```
```sh
cc main.c -Iinclude -L. -lftprintf -o demo && ./demo
```
## Algorithm and data structures
### Main loop
Before printing anything, `ft_printf` checks the whole format string with
`ft_check_format`. If a `%` is not followed by a conversion (for example,
`"abc%"` or `"%5"`), it returns `-1` without writing anything, like glibc.
This is not buffering: once the format is valid, output is still written as
soon as it is ready, as the subject requires.
`ft_printf` then reads the format string one character at a time:
1. An ordinary character is written right away with `write`.
2. A `%` starts a conversion specifier. The specifier is parsed into a
`t_arg` structure, printed by the matching `print_*` function, and then
skipped in the format string.
3. Every printing function returns how many characters it wrote, and
`ft_printf` adds them up.
### Data structure
Each conversion is described by a `t_arg` structure, which is allocated for
that conversion and freed once it has been printed:
```c
typedef struct s_arg
{
char arg; /* conversion character: c s p d i u x X % */
int padding; /* minimum field width */
int minus; /* '-' flag: width for left justification */
int zero; /* '0' flag: width to fill with zeros */
int dot; /* precision */
int hash; /* '#' flag */
int space; /* ' ' flag */
int plus; /* '+' flag */
} t_arg;
```
Every field starts at `-1`, meaning "not set". This keeps "not given" (`-1`)
separate from "given as zero" (`0`), which matters for things like `%.0d`.
A plain conversion such as `%d` leaves every flag at `-1`, so the mandatory
conversions follow the same path with no special case.
### Processing a conversion
1. **Find the conversion** (`ft_main_arg`): skip flag, width and precision
characters (`-0# +.` and digits). The first other character is the
conversion.
2. **Parse** (`ft_parsing`): walk the specifier and fill in the `t_arg`.
Each flag stores the number written right after it, the precision is read
after the `.`, and the width is read backwards from the `.` or the
conversion character. If `-` is present, `0` is ignored, as the C standard
requires.
3. **Print** (`print_*`): `ft_print_arg_flags` fetches the argument with
`va_arg` using the matching type. Each `print_*` function works out its own
padding, in this order: leading spaces, then the sign or `0x` prefix, then
zeros (from the `0` flag or the precision), then the digits. A trailing
`-` field is padded with spaces at the end, in `ft_print_arg_flags`.
4. **Skip** (`ft_to_skip`): move the format index past the whole specifier.
### Printing numbers
Numbers are printed by the recursive functions `ft_putnbr_base` (for
`unsigned int`) and `ft_putnbr_base_ll` (for 64-bit pointers). They first
recurse on `nbr / base_size`, then write `base[nbr % base_size]`, so the digits
come out in the right order without a temporary buffer. The same functions
print decimal, lowercase hexadecimal and uppercase hexadecimal, just by
changing the base string. A negative `int` is turned into its absolute value
as an `unsigned int` before printing, so `INT_MIN` works without overflow.
### Error handling
On failure, every printing function returns a negative value (`-1` from
`write`, or a large negative sentinel from the helpers). After each step,
`ft_printf` checks whether the running total went down. If it did,
`ft_printf` stops and returns `-1`. A conversion that prints nothing, such as
`%s` with `""` or `%.0d` with `0`, adds 0 and is not an error.
### Why this design
This layout has one small parser and one function per conversion. Supporting a
new flag means adding a field to `t_arg`, a case in the parser and the related
padding logic, without changing the main loop.
## Resources
- [`printf(3)` man page](https://man7.org/linux/man-pages/man3/printf.3.html):
how flags, width and precision behave
- [`stdarg(3)` man page](https://man7.org/linux/man-pages/man3/stdarg.3.html):
variadic functions
- [cppreference: `printf`](https://en.cppreference.com/w/c/io/fprintf):
the full conversion specification
- The C standard (ISO/IEC 9899), section 7.21.6.1, on the `fprintf` function
- The 42 Norm, for code style
### Use of AI
The implementation was written by hand. An AI assistant (Claude) was used at
the end of the project to:
- **Review the code against the subject and the real `printf`.** It wrote a
test program that compares the output and return value of `ft_printf` with
glibc's `printf` on many edge cases (empty strings, `NULL`, `INT_MIN`,
zero precision, flag combinations, trailing `%`). It also ran the tests with
AddressSanitizer and UBSan.
- **Fix the bugs it found, with minimal changes.** These were: empty output
being treated as an error, field width being lost when combined with
`#`/`+`/space, `0` not being ignored with `-`, the `#` prefix on zero, and
signed overflow on `INT_MIN`.
- **Merge the mandatory and bonus implementations into a single version**, and
check the format before printing so an incomplete `%` returns `-1` without
any output.
- **Write this README.**
Every change was reviewed and understood before it was kept.
-108
View File
@@ -1,108 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_printf_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 10:54:03 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:59:50 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
static int ft_print_arg_flags(t_arg *arg, va_list args)
{
int count;
count = 0;
if (arg->arg == 'c')
count += print_char(arg, va_arg(args, int));
else if (arg->arg == 's')
count += print_str(arg, va_arg(args, char *));
else if (arg->arg == 'p')
count += print_pointer(arg, va_arg(args, long long));
else if (arg->arg == 'd' || arg->arg == 'i')
count += print_number(arg, va_arg(args, int));
else if (arg->arg == 'u')
count += print_unsigned(arg, va_arg(args, unsigned int));
else if (arg->arg == 'x' || arg->arg == 'X')
count += print_hex(arg, va_arg(args, unsigned int));
if (count < 0)
return (-1);
count += print_chars(arg->minus - count, ' ');
if (count < 0)
return (-1);
return (count);
}
static int ft_print_arg(char *str, va_list args)
{
t_arg *arg;
int count;
arg = ft_parsing(str);
if (!arg)
return (-1);
if (arg->arg == '%')
count = write(1, "%", 1);
else
count = ft_print_arg_flags(arg, args);
free(arg);
return (count);
}
static int ft_to_skip(char *str)
{
int count;
count = 0;
while (!(*str == 'c' || *str == 's' || *str == 'p' || *str == 'd'
|| *str == 'i' || *str == 'u' || *str == 'x' || *str == 'X'
|| *str == '%') && *str)
{
count++;
str++;
}
return (count);
}
static int handle_arg(const char *s, va_list args, int *i)
{
int n;
(*i)++;
n = ft_print_arg((char *)&s[*i], args);
*i += ft_to_skip((char *)&s[*i]);
return (n);
}
int ft_printf(const char *first_arg, ...)
{
va_list args;
int nb_print;
int i;
int temp;
if (!first_arg)
return (-1);
nb_print = 0;
i = -1;
va_start(args, first_arg);
while (first_arg[++i])
{
temp = nb_print;
if (first_arg[i] == '%' && first_arg[i + 1])
nb_print += handle_arg(first_arg, args, &i);
else if (first_arg[i] != '%')
nb_print += write(1, &first_arg[i], 1);
if (temp >= nb_print)
return (-1);
}
va_end(args);
return (nb_print);
}
-70
View File
@@ -1,70 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_putnbr_base_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:16:44 by dgaillet #+# #+# */
/* Updated: 2025/11/21 15:04:59 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static int ft_putnbr_base_extra(unsigned int nbr, char *base, int base_size)
{
int i;
char temp;
if (nbr == 0)
return (0);
i = 1 + ft_putnbr_base_extra(nbr / base_size, base, base_size);
temp = base[nbr % base_size];
if (write(1, &temp, 1) < 0)
return (-10000);
return (i);
}
int ft_putnbr_base(unsigned int nbr, char *base, int base_size, int limit)
{
char temp;
if (nbr == 0 && limit != 0)
{
temp = base[0];
if (write(1, &temp, 1) < 0)
return (-10000);
return (1);
}
return (ft_putnbr_base_extra(nbr, base, base_size));
}
static int ft_putnbr_base_ll_extra(unsigned long long nbr, char *base,
int base_size)
{
int i;
char temp;
if (nbr == 0)
return (0);
i = 1 + ft_putnbr_base_ll_extra(nbr / base_size, base, base_size);
temp = base[nbr % base_size];
if (write(1, &temp, 1) < 0)
return (-10000);
return (i);
}
int ft_putnbr_base_ll(unsigned long long nbr, char *base, int base_size)
{
char temp;
if (nbr == 0)
{
temp = base[0];
if (write(1, &temp, 1) < 0)
return (-10000);
return (1);
}
return (ft_putnbr_base_ll_extra(nbr, base, base_size));
}
-28
View File
@@ -1,28 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_char_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 11:56:36 by dgaillet #+# #+# */
/* Updated: 2025/11/21 15:31:35 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include <unistd.h>
int print_char(t_arg *arg, char c)
{
int count;
count = 0;
count += print_chars(arg->padding - 1, ' ');
if (!arg->minus && arg->zero)
count += print_chars(arg->zero - 1, ' ');
if (write(1, &c, 1) < 0)
return (-10000);
count++;
return (count);
}
-84
View File
@@ -1,84 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_hex_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:06:35 by dgaillet #+# #+# */
/* Updated: 2025/11/21 15:39:21 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include <unistd.h>
static int padding_size(t_arg *arg, unsigned int nbr)
{
int padding;
int nbr_size;
if (arg->padding < 0)
return (0);
padding = arg->padding;
nbr_size = nbr_size_base(nbr, 16);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
return (padding);
}
static int print_nb_flags(t_arg *arg, unsigned int nbr)
{
int count;
int padding;
padding = padding_size(arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
if (arg->dot >= 0)
arg->zero = -1;
return (count);
}
static int print_hex_zero(t_arg *arg)
{
int count;
count = 0;
if (write(1, "0", 1) < 0)
return (-10000);
count++;
count += print_chars(arg->zero - 1, '0');
count += print_chars(arg->dot - 1, '0');
return (count);
}
int print_hex(t_arg *arg, unsigned int nbr)
{
int count;
int temp;
count = 0;
count += print_nb_flags(arg, nbr);
if (nbr == 0 && arg->dot)
count += print_hex_zero(arg);
else
{
temp = count;
if (arg->hash > 0 && arg->arg == 'X')
count += write(1, "0X", 2);
else if (arg->hash > 0)
count += write(1, "0x", 2);
if (temp > count)
return (-10000);
count += print_chars(arg->zero - count - nbr_size_base(nbr, 16), '0');
count += print_chars(arg->dot - nbr_size_base(nbr, 16), '0');
if (arg->arg == 'X')
count += ft_putnbr_base(nbr, "0123456789ABCDEF", 16, arg->dot);
else
count += ft_putnbr_base(nbr, "0123456789abcdef", 16, arg->dot);
}
return (count);
}
-87
View File
@@ -1,87 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_number_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */
/* Updated: 2025/11/21 17:08:15 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include <unistd.h>
static int padding_size(int space, int plus, t_arg *arg, int nbr)
{
int padding;
int nbr_size;
unsigned int temp;
if (arg->padding < 0)
return (0);
padding = arg->padding - space - plus;
if (nbr < 0)
{
temp = nbr * -1;
nbr_size = nbr_size_base(temp, 10);
}
else
nbr_size = nbr_size_base(nbr, 10);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
if (nbr < 0)
padding--;
return (padding);
}
static int print_nb_flags(t_arg *arg, int nbr)
{
int count;
int space;
int padding;
int plus;
if (arg->plus >= 0 && nbr >= 0)
plus = 1;
else
plus = 0;
if (arg->plus >= 0 || arg->space < 0)
space = 0;
else
space = 1;
padding = padding_size(space, plus, arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
if (nbr >= 0)
count += print_chars(space, ' ');
count += print_chars(plus, '+');
return (count);
}
int print_number(t_arg *arg, int nbr)
{
unsigned int p_nbr;
int count;
count = 0;
p_nbr = nbr;
count += print_nb_flags(arg, nbr);
if (nbr < 0)
{
if (write(1, "-", 1) < 0)
return (-10000);
count++;
p_nbr = nbr * -1;
if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(p_nbr, 10) - 1, '0');
}
else if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(p_nbr, 10), '0');
count += print_chars(arg->dot - nbr_size_base(p_nbr, 10), '0');
count += ft_putnbr_base(p_nbr, "0123456789", 10, arg->dot);
return (count);
}
-33
View File
@@ -1,33 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_pointer_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:19:16 by dgaillet #+# #+# */
/* Updated: 2025/11/21 15:46:51 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include "libft.h"
#include <unistd.h>
int print_pointer(t_arg *arg, unsigned long long p)
{
int count;
count = 0;
if (!p)
{
count += print_chars(arg->padding - 5, ' ');
if (write(1, "(nil)", 5) < 0)
return (-10000);
return (5 + count);
}
count += print_chars(arg->padding - nbr_size_base(p, 16) - 2, ' ');
if (write(1, "0x", 2) < 0)
return (-10000);
return (count + 2 + ft_putnbr_base_ll(p, "0123456789abcdef", 16));
}
-40
View File
@@ -1,40 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_str_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:02:03 by dgaillet #+# #+# */
/* Updated: 2025/11/21 15:32:08 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include "libft.h"
int print_str(t_arg *arg, char *str)
{
int count;
count = 0;
if (!str)
{
if (arg->dot < 6 && arg->dot >= 0)
return (print_chars(arg->padding, ' '));
if (arg->padding > 6)
count += print_chars(arg->padding - 6, ' ');
if (write(1, "(null)", 6) < 0)
return (-10000);
return (count + 6);
}
if (arg->dot > (int)ft_strlen(str) || arg->dot < 0)
arg->dot = ft_strlen(str);
if (arg->padding > 0)
count += print_chars(arg->padding - arg->dot, ' ');
else if (!str[0] && arg->space > 0)
return (write(1, " ", 1));
if (write(1, str, arg->dot) < 0)
return (-10000);
return (count + arg->dot);
}
-54
View File
@@ -1,54 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print_unsigned_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:22:44 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#include "ft_printf_bonus.h"
#include <unistd.h>
static int padding_size(t_arg *arg, unsigned int nbr)
{
int padding;
int nbr_size;
if (arg->padding < 0)
return (0);
padding = arg->padding;
nbr_size = nbr_size_base(nbr, 10);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
return (padding);
}
static int print_nb_flags(t_arg *arg, unsigned int nbr)
{
int count;
int padding;
padding = padding_size(arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
return (count);
}
int print_unsigned(t_arg *arg, unsigned int nbr)
{
int count;
count = 0;
count += print_nb_flags(arg, nbr);
if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(nbr, 10), '0');
count += print_chars(arg->dot - nbr_size_base(nbr, 10), '0');
count += ft_putnbr_base(nbr, "0123456789", 10, arg->dot);
return (count);
}
+31 -9
View File
@@ -6,23 +6,45 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 10:52:23 by dgaillet #+# #+# */ /* Created: 2025/11/17 10:52:23 by dgaillet #+# #+# */
/* Updated: 2025/11/17 12:47:41 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 12:10:56 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef FT_PRINTF_H #ifndef FT_PRINTF_H
# define FT_PRINTF_H # define FT_PRINTF_H
int ft_printf(const char *first_arg, ...) __attribute__((format(printf, 1, 2))); typedef struct s_arg
{
char arg;
int padding;
int minus;
int zero;
int dot;
int hash;
int space;
int plus;
} t_arg;
int ft_printf(const char *first_arg, ...) __attribute__((format(printf,
1, 2)));
int ft_printf(const char *first_arg, ...); int ft_printf(const char *first_arg, ...);
int ft_putnbr_base(unsigned long long nbr, char *base, int base_size); int ft_putnbr_base_ll(unsigned long long nbr, char *base,
int base_size);
int ft_putnbr_base(unsigned int nbr, char *base, int base_size,
int limit);
char ft_main_arg(char *str);
int ft_check_format(const char *str);
t_arg *ft_create_arg(void);
t_arg *ft_parsing(char *str);
int print_chars(int nb, char c);
int nbr_size_base(unsigned long long nb, int base_size);
int print_char(char c); int print_char(t_arg *arg, char c);
int print_str(char *str); int print_str(t_arg *arg, char *str);
int print_pointer(unsigned long long p); int print_pointer(t_arg *arg, unsigned long long p);
int print_number(int nbr); int print_number(t_arg *arg, int nbr);
int print_unsigned(unsigned int nbr); int print_unsigned(t_arg *arg, unsigned int nbr);
int print_hex(unsigned long long p, int upper); int print_hex(t_arg *arg, unsigned int nbr);
#endif #endif
-49
View File
@@ -1,49 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_printf_bonus.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 10:52:23 by dgaillet #+# #+# */
/* Updated: 2025/11/21 12:10:56 by dgaillet ### ########lyon.fr */
/* */
/* ************************************************************************** */
#ifndef FT_PRINTF_BONUS_H
# define FT_PRINTF_BONUS_H
typedef struct s_arg
{
char arg;
int padding;
int minus;
int zero;
int dot;
int hash;
int space;
int plus;
} t_arg;
int ft_printf(const char *first_arg, ...) __attribute__((format(printf,
1, 2)));
int ft_printf(const char *first_arg, ...);
int ft_putnbr_base_ll(unsigned long long nbr, char *base,
int base_size);
int ft_putnbr_base(unsigned int nbr, char *base, int base_size,
int limit);
char ft_main_arg(char *str);
t_arg *ft_create_arg(void);
t_arg *ft_parsing(char *str);
int print_chars(int nb, char c);
int nbr_size_base(unsigned long long nb, int base_size);
int print_char(t_arg *arg, char c);
int print_str(t_arg *arg, char *str);
int print_pointer(t_arg *arg, unsigned long long p);
int print_number(t_arg *arg, int nbr);
int print_unsigned(t_arg *arg, unsigned int nbr);
int print_hex(t_arg *arg, unsigned int nbr);
#endif
@@ -1,7 +1,7 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* ft_create_arg_bonus.c :+: :+: :+: */ /* ft_create_arg.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
@@ -10,7 +10,7 @@
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf_bonus.h" #include "ft_printf.h"
#include <stdlib.h> #include <stdlib.h>
t_arg *ft_create_arg(void) t_arg *ft_create_arg(void)
@@ -10,21 +10,34 @@
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
static int is_main_arg(char c) static int is_flag(char c)
{ {
if (c == 'c' || c == 's' || c == 'p' || c == 'd' || c == 'i' || c == 'u' if ((c >= '0' && c <= '9') || c == '-' || c == '#' || c == ' '
|| c == 'x' || c == 'X' || c == '%') || c == '+' || c == '.')
return (1); return (1);
return (0); return (0);
} }
char ft_main_arg(char *str) char ft_main_arg(char *str)
{ {
while (*str) while (*str && is_flag(*str))
{
if (is_main_arg(*str))
break ;
str++; str++;
}
return (*str); return (*str);
} }
int ft_check_format(const char *str)
{
while (*str)
{
if (*str == '%')
{
str++;
while (*str && is_flag(*str))
str++;
if (!*str)
return (0);
}
str++;
}
return (1);
}
@@ -1,7 +1,7 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* ft_parsing_bonus.c :+: :+: :+: */ /* ft_parsing.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
@@ -10,7 +10,7 @@
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf_bonus.h" #include "ft_printf.h"
#include "libft.h" #include "libft.h"
static void get_padding(t_arg *arg, char *str) static void get_padding(t_arg *arg, char *str)
@@ -39,15 +39,11 @@ static void ft_parse_str(t_arg *arg, char *str, char main_arg)
str++; str++;
} }
if (*str == '.') if (*str == '.')
{
arg->dot = ft_atoi(str + 1); arg->dot = ft_atoi(str + 1);
if (!(arg->minus >= 0 || arg->hash >= 0 || arg->space >= 0 if (arg->minus < 0)
|| arg->plus >= 0))
get_padding(arg, str);
}
else if (!(arg->minus >= 0 || arg->hash >= 0 || arg->space >= 0
|| arg->plus >= 0))
get_padding(arg, str); get_padding(arg, str);
else
arg->zero = -1;
} }
t_arg *ft_parsing(char *str) t_arg *ft_parsing(char *str)
+73 -28
View File
@@ -6,33 +6,81 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 10:54:03 by dgaillet #+# #+# */ /* Created: 2025/11/17 10:54:03 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:47:19 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 14:59:50 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h" #include "ft_printf.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
static int ft_print_arg(char c, va_list args) static int ft_print_arg_flags(t_arg *arg, va_list args)
{ {
if (c == 'c') int count;
return (print_char(va_arg(args, int)));
else if (c == 's') count = 0;
return (print_str(va_arg(args, char *))); if (arg->arg == 'c')
else if (c == 'p') count += print_char(arg, va_arg(args, int));
return (print_pointer(va_arg(args, unsigned long long))); else if (arg->arg == 's')
else if (c == 'd' || c == 'i') count += print_str(arg, va_arg(args, char *));
return (print_number(va_arg(args, int))); else if (arg->arg == 'p')
else if (c == 'u') count += print_pointer(arg, va_arg(args, long long));
return (print_unsigned(va_arg(args, unsigned int))); else if (arg->arg == 'd' || arg->arg == 'i')
else if (c == 'x') count += print_number(arg, va_arg(args, int));
return (print_hex(va_arg(args, unsigned int), 0)); else if (arg->arg == 'u')
else if (c == 'X') count += print_unsigned(arg, va_arg(args, unsigned int));
return (print_hex(va_arg(args, unsigned int), 1)); else if (arg->arg == 'x' || arg->arg == 'X')
else if (c == '%') count += print_hex(arg, va_arg(args, unsigned int));
return (print_char('%')); else
return (0); return (-1);
if (count < 0)
return (-1);
count += print_chars(arg->minus - count, ' ');
if (count < 0)
return (-1);
return (count);
}
static int ft_print_arg(char *str, va_list args)
{
t_arg *arg;
int count;
arg = ft_parsing(str);
if (!arg)
return (-1);
if (arg->arg == '%')
count = write(1, "%", 1);
else
count = ft_print_arg_flags(arg, args);
free(arg);
return (count);
}
static int ft_to_skip(char *str)
{
int count;
count = 0;
while (!(*str == 'c' || *str == 's' || *str == 'p' || *str == 'd'
|| *str == 'i' || *str == 'u' || *str == 'x' || *str == 'X'
|| *str == '%') && *str)
{
count++;
str++;
}
return (count);
}
static int handle_arg(const char *s, va_list args, int *i)
{
int n;
(*i)++;
n = ft_print_arg((char *)&s[*i], args);
*i += ft_to_skip((char *)&s[*i]);
return (n);
} }
int ft_printf(const char *first_arg, ...) int ft_printf(const char *first_arg, ...)
@@ -42,22 +90,19 @@ int ft_printf(const char *first_arg, ...)
int i; int i;
int temp; int temp;
if (!first_arg) if (!first_arg || !ft_check_format(first_arg))
return (-1); return (-1);
nb_print = 0; nb_print = 0;
va_start(args, first_arg);
i = -1; i = -1;
va_start(args, first_arg);
while (first_arg[++i]) while (first_arg[++i])
{ {
temp = nb_print; temp = nb_print;
if (first_arg[i] == '%' && first_arg[i + 1] != '\0') if (first_arg[i] == '%')
{ nb_print += handle_arg(first_arg, args, &i);
i++; else
nb_print += ft_print_arg(first_arg[i], args);
}
else if (first_arg[i] != '%')
nb_print += write(1, &first_arg[i], 1); nb_print += write(1, &first_arg[i], 1);
if (temp >= nb_print) if (temp > nb_print)
return (-1); return (-1);
} }
va_end(args); va_end(args);
+46 -3
View File
@@ -6,22 +6,65 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:16:44 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:16:44 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:49:36 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 15:04:59 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "libft.h" #include "libft.h"
int ft_putnbr_base(unsigned long long nbr, char *base, int base_size) static int ft_putnbr_base_extra(unsigned int nbr, char *base, int base_size)
{ {
int i; int i;
char temp; char temp;
if (nbr == 0) if (nbr == 0)
return (0); return (0);
i = 1 + ft_putnbr_base(nbr / base_size, base, base_size); i = 1 + ft_putnbr_base_extra(nbr / base_size, base, base_size);
temp = base[nbr % base_size]; temp = base[nbr % base_size];
if (write(1, &temp, 1) < 0) if (write(1, &temp, 1) < 0)
return (-10000); return (-10000);
return (i); return (i);
} }
int ft_putnbr_base(unsigned int nbr, char *base, int base_size, int limit)
{
char temp;
if (nbr == 0 && limit != 0)
{
temp = base[0];
if (write(1, &temp, 1) < 0)
return (-10000);
return (1);
}
return (ft_putnbr_base_extra(nbr, base, base_size));
}
static int ft_putnbr_base_ll_extra(unsigned long long nbr, char *base,
int base_size)
{
int i;
char temp;
if (nbr == 0)
return (0);
i = 1 + ft_putnbr_base_ll_extra(nbr / base_size, base, base_size);
temp = base[nbr % base_size];
if (write(1, &temp, 1) < 0)
return (-10000);
return (i);
}
int ft_putnbr_base_ll(unsigned long long nbr, char *base, int base_size)
{
char temp;
if (nbr == 0)
{
temp = base[0];
if (write(1, &temp, 1) < 0)
return (-10000);
return (1);
}
return (ft_putnbr_base_ll_extra(nbr, base, base_size));
}
+13 -3
View File
@@ -6,13 +6,23 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 11:56:36 by dgaillet #+# #+# */ /* Created: 2025/11/17 11:56:36 by dgaillet #+# #+# */
/* Updated: 2025/11/17 12:45:57 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 15:31:35 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h"
#include <unistd.h> #include <unistd.h>
int print_char(char c) int print_char(t_arg *arg, char c)
{ {
return (write(1, &c, 1)); int count;
count = 0;
count += print_chars(arg->padding - 1, ' ');
if (!arg->minus && arg->zero)
count += print_chars(arg->zero - 1, ' ');
if (write(1, &c, 1) < 0)
return (-10000);
count++;
return (count);
} }
+71 -7
View File
@@ -6,19 +6,83 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:06:35 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:06:35 by dgaillet #+# #+# */
/* Updated: 2025/11/17 12:46:47 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 15:39:21 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h" #include "ft_printf.h"
#include <unistd.h> #include <unistd.h>
int print_hex(unsigned long long nbr, int upper) static int padding_size(t_arg *arg, unsigned int nbr)
{ {
if (nbr == 0) int padding;
return (write(1, "0", 1)); int nbr_size;
if (upper)
return (ft_putnbr_base(nbr, "0123456789ABCDEF", 16)); if (arg->padding < 0)
return (0);
padding = arg->padding;
nbr_size = nbr_size_base(nbr, 16);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
if (arg->hash > 0)
padding -= 2;
return (padding);
}
static int print_nb_flags(t_arg *arg, unsigned int nbr)
{
int count;
int padding;
if (!nbr)
arg->hash = -1;
padding = padding_size(arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
if (arg->dot >= 0)
arg->zero = -1;
return (count);
}
static int print_hex_zero(t_arg *arg)
{
int count;
count = 0;
if (write(1, "0", 1) < 0)
return (-10000);
count++;
count += print_chars(arg->zero - 1, '0');
count += print_chars(arg->dot - 1, '0');
return (count);
}
int print_hex(t_arg *arg, unsigned int nbr)
{
int count;
int temp;
count = 0;
count += print_nb_flags(arg, nbr);
if (nbr == 0 && arg->dot)
count += print_hex_zero(arg);
else else
return (ft_putnbr_base(nbr, "0123456789abcdef", 16)); {
temp = count;
if (arg->hash > 0 && arg->arg == 'X')
count += write(1, "0X", 2);
else if (arg->hash > 0)
count += write(1, "0x", 2);
if (temp > count)
return (-10000);
count += print_chars(arg->zero - count - nbr_size_base(nbr, 16), '0');
count += print_chars(arg->dot - nbr_size_base(nbr, 16), '0');
if (arg->arg == 'X')
count += ft_putnbr_base(nbr, "0123456789ABCDEF", 16, arg->dot);
else
count += ft_putnbr_base(nbr, "0123456789abcdef", 16, arg->dot);
}
return (count);
} }
+69 -9
View File
@@ -6,24 +6,84 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */
/* Updated: 2025/11/17 12:56:40 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 17:08:15 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h" #include "ft_printf.h"
#include <unistd.h> #include <unistd.h>
int print_number(int nbr) static int padding_size(int space, int plus, t_arg *arg, int nbr)
{ {
unsigned int p_nbr; int padding;
int nbr_size;
unsigned int temp;
if (nbr == 0) if (arg->padding < 0)
return (write(1, "0", 1)); return (0);
padding = arg->padding - space - plus;
if (nbr < 0) if (nbr < 0)
{ {
write(1, "-", 1); temp = (unsigned int)nbr * -1;
p_nbr = nbr * -1; nbr_size = nbr_size_base(temp, 10);
return (1 + ft_putnbr_base(p_nbr, "0123456789", 10));
} }
return (ft_putnbr_base(nbr, "0123456789", 10)); else
nbr_size = nbr_size_base(nbr, 10);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
if (nbr < 0)
padding--;
return (padding);
}
static int print_nb_flags(t_arg *arg, int nbr)
{
int count;
int space;
int padding;
int plus;
if (arg->plus >= 0 && nbr >= 0)
plus = 1;
else
plus = 0;
if (arg->plus >= 0 || arg->space < 0)
space = 0;
else
space = 1;
padding = padding_size(space, plus, arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
if (nbr >= 0)
count += print_chars(space, ' ');
count += print_chars(plus, '+');
return (count);
}
int print_number(t_arg *arg, int nbr)
{
unsigned int p_nbr;
int count;
count = 0;
p_nbr = nbr;
if (nbr >= 0 && (arg->plus >= 0 || arg->space >= 0))
arg->zero--;
count += print_nb_flags(arg, nbr);
if (nbr < 0)
{
if (write(1, "-", 1) < 0)
return (-10000);
count++;
p_nbr = (unsigned int)nbr * -1;
if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(p_nbr, 10) - 1, '0');
}
else if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(p_nbr, 10), '0');
count += print_chars(arg->dot - nbr_size_base(p_nbr, 10), '0');
count += ft_putnbr_base(p_nbr, "0123456789", 10, arg->dot);
return (count);
} }
+12 -6
View File
@@ -6,22 +6,28 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:19:16 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:19:16 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:51:15 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 15:46:51 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h" #include "ft_printf.h"
#include "libft.h" #include "libft.h"
#include <unistd.h>
int print_pointer(unsigned long long p) int print_pointer(t_arg *arg, unsigned long long p)
{ {
int count;
count = 0;
if (!p) if (!p)
{ {
count += print_chars(arg->padding - 5, ' ');
if (write(1, "(nil)", 5) < 0) if (write(1, "(nil)", 5) < 0)
return (-1); return (-10000);
return (5); return (5 + count);
} }
count += print_chars(arg->padding - nbr_size_base(p, 16) - 2, ' ');
if (write(1, "0x", 2) < 0) if (write(1, "0x", 2) < 0)
return (-1); return (-10000);
return (2 + ft_putnbr_base(p, "0123456789abcdef", 16)); return (count + 2 + ft_putnbr_base_ll(p, "0123456789abcdef", 16));
} }
+21 -7
View File
@@ -6,21 +6,35 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:02:03 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:02:03 by dgaillet #+# #+# */
/* Updated: 2025/11/21 14:54:08 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 15:32:08 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h"
#include "libft.h" #include "libft.h"
int print_str(char *str) int print_str(t_arg *arg, char *str)
{ {
int count;
count = 0;
if (!str) if (!str)
{ {
if (arg->dot < 6 && arg->dot >= 0)
return (print_chars(arg->padding, ' '));
if (arg->padding > 6)
count += print_chars(arg->padding - 6, ' ');
if (write(1, "(null)", 6) < 0) if (write(1, "(null)", 6) < 0)
return (-1); return (-10000);
return (6); return (count + 6);
} }
if (write(1, str, ft_strlen(str)) < 0) if (arg->dot > (int)ft_strlen(str) || arg->dot < 0)
return (-1); arg->dot = ft_strlen(str);
return (ft_strlen(str)); if (arg->padding > 0)
count += print_chars(arg->padding - arg->dot, ' ');
else if (!str[0] && arg->space > 0)
return (write(1, " ", 1));
if (write(1, str, arg->dot) < 0)
return (-10000);
return (count + arg->dot);
} }
+38 -5
View File
@@ -6,16 +6,49 @@
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */ /* Created: 2025/11/17 12:26:23 by dgaillet #+# #+# */
/* Updated: 2025/11/17 12:44:47 by dgaillet ### ########lyon.fr */ /* Updated: 2025/11/21 14:22:44 by dgaillet ### ########lyon.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "ft_printf.h" #include "ft_printf.h"
#include <unistd.h> #include <unistd.h>
int print_unsigned(unsigned int nbr) static int padding_size(t_arg *arg, unsigned int nbr)
{ {
if (nbr == 0) int padding;
return (write(1, "0", 1)); int nbr_size;
return (ft_putnbr_base(nbr, "0123456789", 10));
if (arg->padding < 0)
return (0);
padding = arg->padding;
nbr_size = nbr_size_base(nbr, 10);
if (arg->dot > nbr_size || (arg->dot == 0 && !nbr))
nbr_size = arg->dot;
padding = padding - nbr_size;
return (padding);
}
static int print_nb_flags(t_arg *arg, unsigned int nbr)
{
int count;
int padding;
padding = padding_size(arg, nbr);
count = 0;
if (arg->dot >= 0 || arg->zero < 0)
count += print_chars(padding, ' ');
return (count);
}
int print_unsigned(t_arg *arg, unsigned int nbr)
{
int count;
count = 0;
count += print_nb_flags(arg, nbr);
if (arg->dot < 0)
count += print_chars(arg->zero - nbr_size_base(nbr, 10), '0');
count += print_chars(arg->dot - nbr_size_base(nbr, 10), '0');
count += ft_putnbr_base(nbr, "0123456789", 10, arg->dot);
return (count);
} }
@@ -1,7 +1,7 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* utils_flag_bonus.c :+: :+: :+: */ /* utils_flag.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */ /* By: dgaillet <dgaillet@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */