diff --git a/Makefile b/Makefile index d9e336a..a702dd3 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,7 @@ NAME= libftprintf.a LIBFT= $(BUILD_DIR)/libft.a -BONUS= $(BUILD_DIR)/libftprintf_bonus.a SRC_DIR= src -B_SRC_DIR= bonus INC_DIR= include LIBFT_DIR= libft BUILD_DIR= .build @@ -16,25 +14,13 @@ SRC= $(SRC_DIR)/ft_printf.c \ $(SRC_DIR)/print_pointer.c \ $(SRC_DIR)/print_str.c \ $(SRC_DIR)/print_unsigned.c \ - -B_SRC= $(B_SRC_DIR)/ft_printf_bonus.c \ - $(B_SRC_DIR)/ft_putnbr_base_bonus.c \ - $(B_SRC_DIR)/print_char_bonus.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 - + $(SRC_DIR)/ft_create_arg.c \ + $(SRC_DIR)/ft_main_arg.c \ + $(SRC_DIR)/ft_parsing.c \ + $(SRC_DIR)/utils_flag.c OBJ= $(SRC:%.c=$(BUILD_DIR)/%.o) -B_OBJ= $(B_SRC:%.c=$(BUILD_DIR)/%.o) DEP= $(SRC:%.c=$(BUILD_DIR)/%.d) -B_DEP= $(B_SRC:%.c=$(BUILD_DIR)/%.d) CC= cc CFLAGS= -Wall -Wextra -Werror -I$(INC_DIR) -I$(LIBFT_DIR) -MMD -MP @@ -42,8 +28,7 @@ AR= ar rcs all: $(NAME) -bonus: $(BONUS) - cp $(BONUS) $(NAME) +bonus: all $(NAME): $(OBJ) $(LIBFT) cp $(LIBFT) $(NAME) @@ -57,20 +42,16 @@ $(LIBFT): $(MAKE) -C $(LIBFT_DIR) cp $(LIBFT_DIR)/libft.a $(LIBFT) -$(BONUS): $(B_OBJ) $(LIBFT) - cp $(LIBFT) $(BONUS) - $(AR) $(BONUS) $(B_OBJ) - clean: - rm -f $(OBJ) $(DEP) $(B_OBJ) $(B_DEP) + rm -f $(OBJ) $(DEP) $(MAKE) -C $(LIBFT_DIR) clean fclean: clean - rm -f $(NAME) $(BONUS) $(LIBFT) + rm -f $(NAME) $(LIBFT) $(MAKE) -C $(LIBFT_DIR) fclean re: fclean all --include $(DEP) $(B_DEP) +-include $(DEP) .PHONY: all clean fclean re bonus diff --git a/README.md b/README.md new file mode 100644 index 0000000..c32e653 --- /dev/null +++ b/README.md @@ -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. diff --git a/bonus/ft_printf_bonus.c b/bonus/ft_printf_bonus.c deleted file mode 100644 index 833a5d5..0000000 --- a/bonus/ft_printf_bonus.c +++ /dev/null @@ -1,108 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ft_printf_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 -#include -#include - -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); -} diff --git a/bonus/ft_putnbr_base_bonus.c b/bonus/ft_putnbr_base_bonus.c deleted file mode 100644 index 500e3df..0000000 --- a/bonus/ft_putnbr_base_bonus.c +++ /dev/null @@ -1,70 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ft_putnbr_base_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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)); -} diff --git a/bonus/print_char_bonus.c b/bonus/print_char_bonus.c deleted file mode 100644 index a192e05..0000000 --- a/bonus/print_char_bonus.c +++ /dev/null @@ -1,28 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_char_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 - -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); -} diff --git a/bonus/print_hex_bonus.c b/bonus/print_hex_bonus.c deleted file mode 100644 index d64d54a..0000000 --- a/bonus/print_hex_bonus.c +++ /dev/null @@ -1,84 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_hex_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 - -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); -} diff --git a/bonus/print_number_bonus.c b/bonus/print_number_bonus.c deleted file mode 100644 index 3a87ab4..0000000 --- a/bonus/print_number_bonus.c +++ /dev/null @@ -1,87 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_number_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 - -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); -} diff --git a/bonus/print_pointer_bonus.c b/bonus/print_pointer_bonus.c deleted file mode 100644 index e3372a2..0000000 --- a/bonus/print_pointer_bonus.c +++ /dev/null @@ -1,33 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_pointer_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 - -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)); -} diff --git a/bonus/print_str_bonus.c b/bonus/print_str_bonus.c deleted file mode 100644 index 23431a7..0000000 --- a/bonus/print_str_bonus.c +++ /dev/null @@ -1,40 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_str_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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); -} diff --git a/bonus/print_unsigned_bonus.c b/bonus/print_unsigned_bonus.c deleted file mode 100644 index 3e88270..0000000 --- a/bonus/print_unsigned_bonus.c +++ /dev/null @@ -1,54 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* print_unsigned_bonus.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 - -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); -} diff --git a/include/ft_printf.h b/include/ft_printf.h index 6f1ba57..55c9ba8 100644 --- a/include/ft_printf.h +++ b/include/ft_printf.h @@ -6,23 +6,45 @@ /* 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 # define FT_PRINTF_H -int ft_printf(const char *first_arg, ...) __attribute__((format(printf, 1, 2))); -int ft_printf(const char *first_arg, ...); +typedef struct s_arg +{ + char arg; + int padding; + int minus; + int zero; + int dot; + int hash; + int space; + int plus; +} t_arg; -int ft_putnbr_base(unsigned long long nbr, char *base, int base_size); +int ft_printf(const char *first_arg, ...) __attribute__((format(printf, + 1, 2))); +int ft_printf(const char *first_arg, ...); -int print_char(char c); -int print_str(char *str); -int print_pointer(unsigned long long p); -int print_number(int nbr); -int print_unsigned(unsigned int nbr); -int print_hex(unsigned long long p, int upper); +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(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 diff --git a/include/ft_printf_bonus.h b/include/ft_printf_bonus.h deleted file mode 100644 index 7c6fe38..0000000 --- a/include/ft_printf_bonus.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ft_printf_bonus.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: dgaillet +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* 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 diff --git a/bonus/ft_create_arg_bonus.c b/src/ft_create_arg.c similarity index 92% rename from bonus/ft_create_arg_bonus.c rename to src/ft_create_arg.c index 7434ee0..b10d912 100644 --- a/bonus/ft_create_arg_bonus.c +++ b/src/ft_create_arg.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_create_arg_bonus.c :+: :+: :+: */ +/* ft_create_arg.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: dgaillet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "ft_printf_bonus.h" +#include "ft_printf.h" #include t_arg *ft_create_arg(void) diff --git a/bonus/ft_main_arg_bonus.c b/src/ft_main_arg.c similarity index 75% rename from bonus/ft_main_arg_bonus.c rename to src/ft_main_arg.c index e408ce7..28be1cb 100644 --- a/bonus/ft_main_arg_bonus.c +++ b/src/ft_main_arg.c @@ -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' - || c == 'x' || c == 'X' || c == '%') + if ((c >= '0' && c <= '9') || c == '-' || c == '#' || c == ' ' + || c == '+' || c == '.') return (1); return (0); } char ft_main_arg(char *str) { - while (*str) - { - if (is_main_arg(*str)) - break ; + while (*str && is_flag(*str)) 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); +} diff --git a/bonus/ft_parsing_bonus.c b/src/ft_parsing.c similarity index 84% rename from bonus/ft_parsing_bonus.c rename to src/ft_parsing.c index 8f9b17d..6f3ab28 100644 --- a/bonus/ft_parsing_bonus.c +++ b/src/ft_parsing.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ft_parsing_bonus.c :+: :+: :+: */ +/* ft_parsing.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: dgaillet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ @@ -10,7 +10,7 @@ /* */ /* ************************************************************************** */ -#include "ft_printf_bonus.h" +#include "ft_printf.h" #include "libft.h" 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++; } if (*str == '.') - { arg->dot = ft_atoi(str + 1); - if (!(arg->minus >= 0 || arg->hash >= 0 || arg->space >= 0 - || arg->plus >= 0)) - get_padding(arg, str); - } - else if (!(arg->minus >= 0 || arg->hash >= 0 || arg->space >= 0 - || arg->plus >= 0)) + if (arg->minus < 0) get_padding(arg, str); + else + arg->zero = -1; } t_arg *ft_parsing(char *str) diff --git a/src/ft_printf.c b/src/ft_printf.c index 30e8717..1b10cf7 100644 --- a/src/ft_printf.c +++ b/src/ft_printf.c @@ -6,33 +6,81 @@ /* 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 +#include #include -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') - return (print_char(va_arg(args, int))); - else if (c == 's') - return (print_str(va_arg(args, char *))); - else if (c == 'p') - return (print_pointer(va_arg(args, unsigned long long))); - else if (c == 'd' || c == 'i') - return (print_number(va_arg(args, int))); - else if (c == 'u') - return (print_unsigned(va_arg(args, unsigned int))); - else if (c == 'x') - return (print_hex(va_arg(args, unsigned int), 0)); - else if (c == 'X') - return (print_hex(va_arg(args, unsigned int), 1)); - else if (c == '%') - return (print_char('%')); - return (0); + 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)); + else + 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, ...) @@ -42,22 +90,19 @@ int ft_printf(const char *first_arg, ...) int i; int temp; - if (!first_arg) + if (!first_arg || !ft_check_format(first_arg)) return (-1); nb_print = 0; - va_start(args, first_arg); i = -1; + va_start(args, first_arg); while (first_arg[++i]) { temp = nb_print; - if (first_arg[i] == '%' && first_arg[i + 1] != '\0') - { - i++; - nb_print += ft_print_arg(first_arg[i], args); - } - else if (first_arg[i] != '%') + if (first_arg[i] == '%') + nb_print += handle_arg(first_arg, args, &i); + else nb_print += write(1, &first_arg[i], 1); - if (temp >= nb_print) + if (temp > nb_print) return (-1); } va_end(args); diff --git a/src/ft_putnbr_base.c b/src/ft_putnbr_base.c index 43ae1bf..47ed443 100644 --- a/src/ft_putnbr_base.c +++ b/src/ft_putnbr_base.c @@ -6,22 +6,65 @@ /* 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" -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; char temp; if (nbr == 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]; 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)); +} diff --git a/src/print_char.c b/src/print_char.c index 70d8ec3..b446119 100644 --- a/src/print_char.c +++ b/src/print_char.c @@ -6,13 +6,23 @@ /* 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 -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); } diff --git a/src/print_hex.c b/src/print_hex.c index 62c9d40..5fe94ca 100644 --- a/src/print_hex.c +++ b/src/print_hex.c @@ -6,19 +6,83 @@ /* 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 -int print_hex(unsigned long long nbr, int upper) +static int padding_size(t_arg *arg, unsigned int nbr) { - if (nbr == 0) - return (write(1, "0", 1)); - if (upper) - return (ft_putnbr_base(nbr, "0123456789ABCDEF", 16)); + 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; + 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 - 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); } diff --git a/src/print_number.c b/src/print_number.c index 672c1df..a373d89 100644 --- a/src/print_number.c +++ b/src/print_number.c @@ -6,24 +6,84 @@ /* 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 -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) - return (write(1, "0", 1)); + if (arg->padding < 0) + return (0); + padding = arg->padding - space - plus; if (nbr < 0) { - write(1, "-", 1); - p_nbr = nbr * -1; - return (1 + ft_putnbr_base(p_nbr, "0123456789", 10)); + temp = (unsigned int)nbr * -1; + nbr_size = nbr_size_base(temp, 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); } diff --git a/src/print_pointer.c b/src/print_pointer.c index 943265e..6c87984 100644 --- a/src/print_pointer.c +++ b/src/print_pointer.c @@ -6,22 +6,28 @@ /* 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 "libft.h" +#include -int print_pointer(unsigned long long p) +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 (-1); - return (5); + return (-10000); + return (5 + count); } + count += print_chars(arg->padding - nbr_size_base(p, 16) - 2, ' '); if (write(1, "0x", 2) < 0) - return (-1); - return (2 + ft_putnbr_base(p, "0123456789abcdef", 16)); + return (-10000); + return (count + 2 + ft_putnbr_base_ll(p, "0123456789abcdef", 16)); } diff --git a/src/print_str.c b/src/print_str.c index 0827787..c849543 100644 --- a/src/print_str.c +++ b/src/print_str.c @@ -6,21 +6,35 @@ /* 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" -int print_str(char *str) +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 (-1); - return (6); + return (-10000); + return (count + 6); } - if (write(1, str, ft_strlen(str)) < 0) - return (-1); - return (ft_strlen(str)); + 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); } diff --git a/src/print_unsigned.c b/src/print_unsigned.c index 69b6c54..3b33ca7 100644 --- a/src/print_unsigned.c +++ b/src/print_unsigned.c @@ -6,16 +6,49 @@ /* 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 -int print_unsigned(unsigned int nbr) +static int padding_size(t_arg *arg, unsigned int nbr) { - if (nbr == 0) - return (write(1, "0", 1)); - return (ft_putnbr_base(nbr, "0123456789", 10)); + 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); } diff --git a/bonus/utils_flag_bonus.c b/src/utils_flag.c similarity index 94% rename from bonus/utils_flag_bonus.c rename to src/utils_flag.c index c5884a7..93e6ce8 100644 --- a/bonus/utils_flag_bonus.c +++ b/src/utils_flag.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* utils_flag_bonus.c :+: :+: :+: */ +/* utils_flag.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: dgaillet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */