├── .gitignore ├── Makefile ├── README.md ├── en.subject.pdf ├── inc ├── ft_printf.h └── ft_printf_bonus.h ├── src ├── ft_format.c ├── ft_parse.c ├── ft_print_chars.c ├── ft_print_hex.c ├── ft_print_nbrs.c └── ft_printf.c ├── srcb ├── ft_format_bonus.c ├── ft_parse_bonus.c ├── ft_print_chars_bonus.c ├── ft_print_hex_bonus.c ├── ft_print_nbrs_bonus.c └── ft_printf_bonus.c └── tests └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | libft-unit-test/ 2 | libft 3 | libftTester/ 4 | printfTester/ 5 | pft_2019/ 6 | pft/ 7 | 42TESTERS-PRINTF/ 8 | gnlTester/ 9 | a.out 10 | *.o 11 | *.d 12 | *.so 13 | *.a 14 | .DS_Store 15 | tempCodeRunnerFile.c 16 | *.swp 17 | bin/ 18 | obj/ 19 | objb/ 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: aperez-b +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2021/04/17 09:03:14 by aperez-b #+# #+# # 9 | # Updated: 2023/04/05 14:17:35 by aperez-b ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | # Color Aliases 14 | DEFAULT = \033[0;39m 15 | GRAY = \033[0;90m 16 | RED = \033[0;91m 17 | GREEN = \033[0;92m 18 | YELLOW = \033[0;93m 19 | BLUE = \033[0;94m 20 | MAGENTA = \033[0;95m 21 | CYAN = \033[0;96m 22 | WHITE = \033[0;97m 23 | 24 | SHELL=/bin/bash 25 | 26 | # Make variables 27 | PRINTF = printf 28 | CFLAGS = -Wall -Wextra -Werror 29 | RM = rm -f 30 | CC = gcc -MD 31 | AR = ar rcs 32 | SRC_DIR = src 33 | INC_DIR = inc 34 | SRCB_DIR = srcb 35 | OBJ_DIR = obj 36 | OBJB_DIR = objb 37 | BIN_DIR = bin 38 | BIN = libftprintf.a 39 | NAME = $(BIN_DIR)/$(BIN) 40 | LIBFT = libft/bin/libft.a 41 | LIBFT_DIR = libft 42 | LIBFT_SRC = $(shell [ -d libft ] && ls libft/src*/*.c) 43 | 44 | SRC = ft_printf.c \ 45 | ft_format.c \ 46 | ft_parse.c \ 47 | ft_print_chars.c \ 48 | ft_print_nbrs.c \ 49 | ft_print_hex.c 50 | 51 | SRCB = ft_printf_bonus.c \ 52 | ft_format_bonus.c \ 53 | ft_parse_bonus.c \ 54 | ft_print_chars_bonus.c \ 55 | ft_print_nbrs_bonus.c \ 56 | ft_print_hex_bonus.c 57 | 58 | OBJ = $(addprefix $(OBJ_DIR)/, $(SRC:.c=.o)) 59 | 60 | OBJB = $(addprefix $(OBJB_DIR)/, $(SRCB:.c=.o)) 61 | 62 | # Progress vars 63 | SRC_COUNT_TOT := $(shell expr $(shell echo -n $(SRC) | wc -w) - $(shell ls -l $(OBJ_DIR) 2>&1 | grep ".o" | wc -l) + 1) 64 | ifeq ($(shell test $(SRC_COUNT_TOT) -le 0; echo $$?),0) 65 | SRC_COUNT_TOT := $(shell echo -n $(SRC) | wc -w) 66 | endif 67 | SRC_COUNT := 0 68 | SRC_PCT = $(shell expr 100 \* $(SRC_COUNT) / $(SRC_COUNT_TOT)) 69 | SRCB_COUNT_TOT := $(shell expr $(shell echo -n $(SRCB) | wc -w) - $(shell ls -l $(OBJB_DIR) 2>&1 | grep ".o" | wc -l) + 1) 70 | ifeq ($(shell test $(SRCB_COUNT_TOT) -le 0; echo $$?),0) 71 | SRCB_COUNT_TOT := $(shell echo -n $(SRCB) | wc -w) 72 | endif 73 | SRCB_COUNT := 0 74 | SRCB_PCT = $(shell expr 100 \* $(SRCB_COUNT) / $(SRCB_COUNT_TOT)) 75 | 76 | all: $(NAME) 77 | 78 | $(NAME): $(LIBFT) $(OBJ) | $(BIN_DIR) 79 | @$(AR) $(NAME) $(OBJ) 80 | @$(PRINTF) "\r%100s\r$(GREEN)$(BIN) is up to date!$(DEFAULT)\n" 81 | 82 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) 83 | @$(eval SRC_COUNT = $(shell expr $(SRC_COUNT) + 1)) 84 | @$(PRINTF) "\r%100s\r[ %d/%d (%d%%) ] Compiling $(BLUE)$<$(DEFAULT)..." "" $(SRC_COUNT) $(SRC_COUNT_TOT) $(SRC_PCT) 85 | @$(CC) $(CFLAGS) -c $< -o $@ 86 | 87 | bonus: $(LIBFT) $(OBJB) 88 | @$(AR) $(NAME) $(OBJB) 89 | @$(PRINTF) "\r%100s\r$(MAGENTA)Bonus $(BIN) is up to date!$(DEFAULT)\n" 90 | 91 | $(OBJB_DIR)/%.o: $(SRCB_DIR)/%.c | $(OBJB_DIR) 92 | @$(eval SRCB_COUNT = $(shell expr $(SRCB_COUNT) + 1)) 93 | @$(PRINTF) "\r%100s\r[ %d/%d (%d%%) ] Compiling $(MAGENTA)$<$(DEFAULT)..." "" $(SRCB_COUNT) $(SRCB_COUNT_TOT) $(SRCB_PCT) 94 | @$(CC) $(CFLAGS) -c $< -o $@ 95 | 96 | $(LIBFT): $(LIBFT_SRC) | $(LIBFT_DIR) $(BIN_DIR) 97 | @make all -C libft 98 | @$(AR) $(NAME) $(LIBFT) 99 | 100 | test: all 101 | @$(PRINTF) "\n$(YELLOW)Performing test with custom main...$(DEFAULT)\n\n" 102 | @$(CC) tests/main.c 103 | @./a.out $(UNAME) | cat -e 104 | @$(RM) a.out 105 | @$(PRINTF) "$(GREEN)Test Complete!$(DEFAULT)\n" 106 | 107 | clean: | $(LIBFT_DIR) 108 | @$(PRINTF) "$(CYAN)Cleaning up object files in ft_printf...$(DEFAULT)\n" 109 | @make clean -C libft 110 | @$(RM) -r $(OBJ_DIR) 111 | @$(RM) -r $(OBJB_DIR) 112 | 113 | fclean: clean 114 | @$(RM) -r $(BIN_DIR) 115 | @$(RM) $(LIBFT) 116 | @$(PRINTF) "$(CYAN)Removed $(LIBFT)$(DEFAULT)\n" 117 | @$(PRINTF) "$(CYAN)Removed $(NAME)$(DEFAULT)\n" 118 | 119 | norminette: | $(LIBFT_DIR) 120 | @$(PRINTF) "$(CYAN)\nChecking norm for ft_printf...$(DEFAULT)\n" 121 | @norminette -R CheckForbiddenSourceHeader $(SRC_DIR) $(SRCB_DIR) $(INC_DIR) 122 | @make norminette -C libft 123 | 124 | $(LIBFT_DIR): 125 | @git clone https://gitlab.com/madebypixel02/libft.git 126 | 127 | $(OBJ_DIR): 128 | @mkdir -p $(OBJ_DIR) 129 | 130 | $(OBJB_DIR): 131 | @mkdir -p $(OBJB_DIR) 132 | 133 | $(BIN_DIR): 134 | @mkdir -p $(BIN_DIR) 135 | 136 | git: 137 | git add . 138 | git commit 139 | git push 140 | 141 | re: fclean 142 | @make all 143 | 144 | -include $(OBJ_DIR)/*.d 145 | -include $(OBJB_DIR)/*.d 146 | 147 | .PHONY: all clean fclean bonus re norminette test git 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ft_printf | 42 Madrid 2 | 3 | *Because ft_putstr & ft_putnbr aren't enough :stuck_out_tongue_winking_eye:* 4 | 5 |
6 | 7 |
8 | 9 | ### Table of Contents 10 | 11 | * [ft_print what?](#ft_print-what) 12 | * [Capabilities](#capabilities) 13 | * [Bonus](#bonus) 14 | * [Limitations](#limitations) 15 | * [Installation](#installation) 16 | * [Summary](#summary) 17 | 18 | ## ft_print what? 19 | Printf is likely one of the most popular commands people see when learning a new programming language, and for a good reason. They are easy to understand and very powerful too. This is why learning to implement our own version of printf can help us better understand what happens internally when entering ``printf("Hello World")``! 20 | 21 | ## Capabilities 22 | Our version of the printf function will be called ``ft_printf``, and will be able to work with the following inputs: 23 | 24 | 25 | * Specifiers 26 | 27 | | Specifier | Description | 28 | | :-------: | :---------: | 29 | | ``%`` | Prints the percent character | 30 | | ``c`` | Prints a character | 31 | | ``s`` | Prints a string (array of characters) | 32 | | ``d``,``i`` | Prints an integer | 33 | | ``p`` | Prints pointer address (hex starting with ``0x``) | 34 | | ``u`` | Prints an unsigned integer | 35 | | ``x`` | Prints an unsigned hexadecimal integer (lowecase a-f) | 36 | | ``X`` | Prints an unsigned hexadecimal integer (uppercase A-F) | 37 | 38 | * Flags 39 | 40 | | Flag | Description | 41 | | :--: | :---------: | 42 | | (width) | Specifies the minimum width of the printed variable (adds spaces when necessary) | 43 | | (precision) | Selects the minimum number of elements of the variable that are printed (Eg. number of chars from a string) | 44 | | ``-`` | Pads text to the left (adds spaces to the right) | 45 | | ``0`` | Pads text with zeroes instead of spaces | 46 | | ``.`` | Separates Width and Precision | 47 | | ``*`` | Indicates that the Width or the Precision will be specified using an additional variable | 48 | 49 | Our ft_printf function has the following prototype: 50 | ```C 51 | int ft_printf(const char *str, ...); 52 | ``` 53 | 54 | The general idea of the function is to iterate over ``str`` and print normally until a ``%`` is read. From there, we parse the next elements until one of the Specifiers is found or until the end of the string ``\0`` is reached, whichever comes first. The general structure of the elements we want to parse is the following: 55 | 56 | ``` 57 | %[Flags][Width].[Precision][Specifier] 58 | ``` 59 | 60 | ## Bonus 61 | As of July 2021, the subject for this project has changed, and the flags ``-0.`` are now part of the bonuses. Also the ``*`` flag is gone entirely, though I have decided to keep it in my version of the code, since it took a while to implement and I wish to keep it. Other flags we need to implement in this bonus part are: 62 | 63 | | Bonus Flag | Description | 64 | | :--------: | :---------: | 65 | | ``#`` | Adds "0X" or "0x" to conversions with hexadecimal specifiers (excluding p) for values other than zero | 66 | | (space) |A blank space is added provided that no sign is specified | 67 | | ``+`` | Adds a plus sign in front of positive numbers | 68 | 69 | ## Limitations 70 | 71 | As this is quite a straightforward approach at printf, there are a few limitations to consider, namely: 72 | 73 | * Our ``ft_printf`` does not have buffer management, unlike the real printf 74 | * This implementation of printf doesn't handle overflows and unexpected inputs the same way the real printf would 75 | * Our ``ft_printf`` isn't nearly as powerful as the real prinft since many features are not included 76 | * ``ft_printf`` relies on our personal libft library, which makes it slower in performance when compared to the original printf 77 | 78 | ## Installation 79 | 80 | In order for you to test this printf, it is recommended that you install the following dependencies: 81 | 82 | ```shell 83 | gcc clang python-norminette make 84 | ``` 85 | For Linux users, it is also recommended to install ``valgrind`` (Leak checker) 86 | 87 | * Testing the ``ft_printf`` function 88 | ```shell 89 | git clone https://gitlab.com/madebypixel02/ft_printf.git 90 | cd ft_printf 91 | make 92 | ``` 93 | Feel free to replace your own libft inside the ``ft_printf`` folder 94 | 95 | 96 | * Usage: 97 | 98 | The makefile compiles all files from the ``src/`` or ``srcb/`` folders and saves the object files to the ``obj/`` and ``objb/`` folders. It then generates the output file ``libftprintf.a`` inside the ``bin/`` folder. Here are some of the commands you can try: 99 | 100 | ``` 101 | make all Compiles the libftprintf.a file 102 | make test Compiles ft_printf and libft with a custom main. Checks for leaks in Mac and Linux 103 | make bonus Compiles all bonus files instead of the mandatory ones 104 | make norminette Checks Norm for both printf and libft files 105 | make git Stages every modified file to commit and pushes to upstream branch 106 | ``` 107 | 108 | * Example: 109 | 110 | ![ft_printf](https://user-images.githubusercontent.com/40824677/146548168-c5f4142c-b174-44fe-9c20-11f113bd746d.gif) 111 | 112 | ## Summary 113 | 114 | This was my second project as a 42 student in Madrid. Looking forward to the new projects coming next! 115 | 116 | July 9th, 2021 117 | -------------------------------------------------------------------------------- /en.subject.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madebypixel02/ft_printf/d60fc14346ae6ce6004d109ba8f62ecbcdd200af/en.subject.pdf -------------------------------------------------------------------------------- /inc/ft_printf.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_printf.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/17 09:11:41 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:00:02 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef FT_PRINTF_H 14 | 15 | # define FT_PRINTF_H 16 | 17 | # include "../libft/inc/libft.h" 18 | # include 19 | 20 | /* Struct to keep track of various format parameters */ 21 | typedef struct s_format 22 | { 23 | int minus; 24 | int plus; 25 | int width; 26 | int precision; 27 | int neg_prec; 28 | char specifier; 29 | int zero; 30 | int dot; 31 | int space; 32 | int sharp; 33 | } t_format; 34 | 35 | # define INT_MIN -2147483648 36 | # define UINT_MAX 4294967295 37 | 38 | /* String containing printf's specifiers */ 39 | # define SPECIFIERS "cspdiuxX%" 40 | 41 | /* Hexadecimal base (lowercase) */ 42 | # define HEXALOW "0123456789abcdef" 43 | 44 | /* Hexadecimal base (uppercase) */ 45 | # define HEXAUP "0123456789ABCDEF" 46 | 47 | /* Custom function to format and print data */ 48 | int ft_printf(const char *str, ...); 49 | 50 | /* Initializes default parameters for new format struct */ 51 | t_format ft_newformat(void); 52 | 53 | /* Calls printing function depending on the specifier */ 54 | int ft_print_format(t_format f, va_list ap); 55 | 56 | /* Prints chars with format */ 57 | int ft_print_c_pct(t_format f, va_list ap); 58 | 59 | /* Prints strings with format */ 60 | int ft_print_s(t_format f, va_list ap); 61 | 62 | /* Prints decimal number with format */ 63 | int ft_print_d_i_u(t_format f, va_list ap); 64 | 65 | /* Prints hexadecimal number with format */ 66 | int ft_print_x(t_format f, va_list ap); 67 | 68 | /* Prints 0x followed by a hexadecimal number with format */ 69 | int ft_print_p(t_format f, va_list ap); 70 | 71 | /* Checks the str after a '%' is found and fills struct */ 72 | int ft_parse(char *str, va_list ap); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /inc/ft_printf_bonus.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_printf_bonus.h :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/09/27 19:30:20 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:30:35 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef FT_PRINTF_BONUS_H 14 | 15 | # define FT_PRINTF_BONUS_H 16 | 17 | # include "../libft/inc/libft.h" 18 | # include 19 | 20 | /* Struct to keep track of various format parameters */ 21 | typedef struct s_format 22 | { 23 | int minus; 24 | int plus; 25 | int width; 26 | int precision; 27 | int neg_prec; 28 | char specifier; 29 | int zero; 30 | int dot; 31 | int space; 32 | int sharp; 33 | } t_format; 34 | 35 | # define INT_MIN -2147483648 36 | # define UINT_MAX 4294967295 37 | 38 | /* String containing printf's specifiers */ 39 | # define SPECIFIERS "cspdiuxX%" 40 | 41 | /* Hexadecimal base (lowercase) */ 42 | # define HEXALOW "0123456789abcdef" 43 | 44 | /* Hexadecimal base (uppercase) */ 45 | # define HEXAUP "0123456789ABCDEF" 46 | 47 | /* Custom function to format and print data */ 48 | int ft_printf(const char *str, ...); 49 | 50 | /* Initializes default parameters for new format struct */ 51 | t_format ft_newformat(void); 52 | 53 | /* Calls printing function depending on the specifier */ 54 | int ft_print_format(t_format f, va_list ap); 55 | 56 | /* Prints chars with format */ 57 | int ft_print_c_pct(t_format f, va_list ap); 58 | 59 | /* Prints strings with format */ 60 | int ft_print_s(t_format f, va_list ap); 61 | 62 | /* Prints decimal number with format */ 63 | int ft_print_d_i_u(t_format f, va_list ap); 64 | 65 | /* Prints hexadecimal number with format */ 66 | int ft_print_x(t_format f, va_list ap); 67 | 68 | /* Prints 0x followed by a hexadecimal number with format */ 69 | int ft_print_p(t_format f, va_list ap); 70 | 71 | /* Checks the str after a '%' is found and fills struct */ 72 | int ft_parse(char *str, va_list ap); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/ft_format.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_format.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/21 08:52:18 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:00:50 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | t_format ft_newformat(void) 16 | { 17 | t_format newformat; 18 | 19 | newformat.minus = 0; 20 | newformat.plus = 0; 21 | newformat.width = 0; 22 | newformat.precision = 0; 23 | newformat.specifier = 0; 24 | newformat.zero = 0; 25 | newformat.dot = 0; 26 | newformat.space = 0; 27 | newformat.sharp = 0; 28 | newformat.neg_prec = 0; 29 | return (newformat); 30 | } 31 | -------------------------------------------------------------------------------- /src/ft_parse.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_parse.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/07/08 09:01:25 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:01:07 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | static t_format ft_parse_bonus(char *str, t_format f) 16 | { 17 | while (*str != '.' && !ft_strchr(SPECIFIERS, *str)) 18 | { 19 | if (*str == '+') 20 | f.plus = 1; 21 | if (*str == ' ') 22 | f.space = 1; 23 | if (*str == '#') 24 | f.sharp = 1; 25 | str++; 26 | } 27 | return (f); 28 | } 29 | 30 | static t_format ft_parse_width(char *str, va_list ap, t_format f) 31 | { 32 | int specified; 33 | 34 | specified = 0; 35 | while (*str != '.' && !ft_strchr(SPECIFIERS, *str)) 36 | { 37 | if (*str == '-') 38 | f.minus = 1; 39 | if (*str == '0' && !ft_isdigit(*(str - 1))) 40 | f.zero = 1; 41 | else if (((*str > '0' && *str <= '9') || *str == '*') && !specified) 42 | { 43 | if (*str == '*') 44 | f.width = va_arg(ap, int); 45 | else 46 | f.width = ft_atoi(str); 47 | specified = 1; 48 | } 49 | str++; 50 | } 51 | return (f); 52 | } 53 | 54 | static t_format ft_parse_precision(char *str, va_list ap, t_format f) 55 | { 56 | int specified; 57 | 58 | specified = 0; 59 | while (!ft_strchr(SPECIFIERS, *str)) 60 | { 61 | if ((ft_isdigit(*str) || *str == '*') && !specified) 62 | { 63 | if (*str == '*') 64 | f.precision = va_arg(ap, int); 65 | else 66 | f.precision = ft_atoi(str); 67 | specified = 1; 68 | } 69 | str++; 70 | } 71 | return (f); 72 | } 73 | 74 | int ft_parse(char *str, va_list ap) 75 | { 76 | t_format new_format; 77 | 78 | new_format = ft_parse_width(str, ap, ft_newformat()); 79 | new_format = ft_parse_bonus(str, new_format); 80 | while (!ft_strchr(SPECIFIERS, *str) && *str != '.') 81 | str++; 82 | if (*str == '.' && !new_format.specifier) 83 | { 84 | new_format.dot = 1; 85 | new_format = ft_parse_precision(str++, ap, new_format); 86 | while (!ft_strchr(SPECIFIERS, *str)) 87 | str++; 88 | } 89 | if (new_format.width < 0) 90 | { 91 | new_format.minus = 1; 92 | new_format.width *= -1; 93 | } 94 | new_format.specifier = *str; 95 | new_format.neg_prec = new_format.precision < 0; 96 | return (ft_print_format(new_format, ap)); 97 | } 98 | -------------------------------------------------------------------------------- /src/ft_print_chars.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_chars.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/22 10:43:07 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:01:31 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | int ft_print_c_pct(t_format f, va_list ap) 16 | { 17 | char c; 18 | int count; 19 | 20 | count = 0; 21 | if (f.specifier == 'c') 22 | c = va_arg(ap, int); 23 | else 24 | c = '%'; 25 | f.precision = 1; 26 | if (!f.minus && f.zero) 27 | count += ft_putnchar_fd('0', 1, f.width - f.precision); 28 | else if (!f.minus && f.width > f.precision) 29 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 30 | count += ft_putchar_fd(c, 1); 31 | if (f.minus && f.width - f.precision > 0) 32 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 33 | return (count); 34 | } 35 | 36 | int ft_print_s(t_format f, va_list ap) 37 | { 38 | char *string; 39 | int count; 40 | 41 | count = 0; 42 | string = va_arg(ap, char *); 43 | if (!string) 44 | string = "(null)"; 45 | if (!f.dot || f.precision > (int)ft_strlen(string) || f.precision < 0) 46 | f.precision = ft_strlen(string); 47 | if (!f.minus && f.width > f.precision && f.zero && (!f.dot || f.neg_prec)) 48 | count += ft_putnchar_fd('0', 1, f.width - f.precision); 49 | else if (!f.minus && f.width - f.precision > 0) 50 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 51 | count += ft_putstrn_fd(string, 1, f.precision); 52 | if (f.minus && f.width - f.precision > 0) 53 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 54 | return (count); 55 | } 56 | -------------------------------------------------------------------------------- /src/ft_print_hex.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_hex.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/21 10:26:21 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:02:10 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | static char *ft_sharp(t_format f) 16 | { 17 | if (f.specifier == 'X') 18 | return ("0X"); 19 | return ("0x"); 20 | } 21 | 22 | static int ft_recursive_hex(t_format f, size_t n, size_t iteration) 23 | { 24 | int count; 25 | int remainder; 26 | char character; 27 | 28 | count = 0; 29 | if (n > 0 || (!iteration && (f.specifier != 'p' || !f.dot))) 30 | { 31 | remainder = n % 16; 32 | if (f.specifier != 'X') 33 | character = HEXALOW[remainder]; 34 | else 35 | character = HEXAUP[remainder]; 36 | n /= 16; 37 | iteration = 1; 38 | count += ft_recursive_hex(f, n, iteration); 39 | count += ft_putchar_fd(character, 1); 40 | } 41 | return (count); 42 | } 43 | 44 | int ft_print_x(t_format f, va_list ap) 45 | { 46 | int count; 47 | unsigned int n; 48 | int len; 49 | 50 | count = 0; 51 | n = va_arg(ap, unsigned int); 52 | len = ft_nbrlen(n, 16); 53 | if (!n && !f.precision && f.dot) 54 | len = 0; 55 | if (f.precision < 0 || f.precision < len || !f.dot) 56 | f.precision = len; 57 | if (f.sharp && n) 58 | f.width -= 2; 59 | count += ft_putstrn_fd(ft_sharp(f), 1, 2 * (f.sharp && f.zero && n)); 60 | if (!f.minus && f.width > f.precision && (!f.dot || f.neg_prec) && f.zero) 61 | count += ft_putnchar_fd('0', 1, (f.width - f.precision)); 62 | else if (!f.minus && f.width > f.precision) 63 | count += ft_putnchar_fd(' ', 1, (f.width - f.precision)); 64 | count += ft_putstrn_fd(ft_sharp(f), 1, 2 * (f.sharp && !f.zero && n)); 65 | count += ft_putnchar_fd('0', 1, (f.precision - len)); 66 | if (len) 67 | count += ft_recursive_hex(f, n, n); 68 | if (f.minus && f.width > f.precision) 69 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 70 | return (count); 71 | } 72 | 73 | int ft_print_p(t_format f, va_list ap) 74 | { 75 | int count; 76 | size_t n; 77 | int len; 78 | 79 | count = 0; 80 | n = va_arg(ap, size_t); 81 | len = ft_nbrlen(n, 16); 82 | len *= !(!n && !f.precision && f.dot); 83 | if (f.precision < len || !f.dot) 84 | f.precision = len; 85 | count += write(1, "0x", 2 * f.zero); 86 | f.width -= 2; 87 | if (!f.minus && f.width > f.precision && !f.dot && f.zero) 88 | count += ft_putnchar_fd('0', 1, (f.width - f.precision)); 89 | else if (!f.minus && f.width > f.precision) 90 | count += ft_putnchar_fd(' ', 1, (f.width - f.precision)); 91 | count += write(1, "0x", 2 * !f.zero); 92 | count += ft_putnchar_fd('0', 1, (f.precision - len) * (n != 0)); 93 | count += ft_putnchar_fd('0', 1, f.precision * (f.dot && !n)); 94 | if (len) 95 | count += ft_recursive_hex(f, n, n); 96 | if (f.minus && f.width > f.precision) 97 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 98 | return (count); 99 | } 100 | -------------------------------------------------------------------------------- /src/ft_print_nbrs.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_nbrs.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/22 09:58:43 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:01:52 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | static char plus(t_format f) 16 | { 17 | if (f.plus) 18 | return ('+'); 19 | return ('-'); 20 | } 21 | 22 | static int ft_print_nbr(t_format f, char *nbr, int len, int neg) 23 | { 24 | int c; 25 | 26 | c = 0; 27 | f.width -= (f.space && !neg && !f.plus && f.width); 28 | if (neg || f.plus) 29 | c += ft_putnchar_fd(plus(f), 1, f.zero && (!f.dot || f.neg_prec)); 30 | else if (f.space) 31 | c += ft_putnchar_fd(' ', 1, f.zero && !f.dot); 32 | if (!f.minus && f.width > f.precision && (!f.dot || f.neg_prec) && f.zero) 33 | c += ft_putnchar_fd('0', 1, f.width - f.precision - neg - f.plus); 34 | else if (!f.minus && f.width > f.precision) 35 | c += ft_putnchar_fd(' ', 1, f.width - f.precision - neg - f.plus); 36 | if (neg || f.plus) 37 | c += ft_putnchar_fd(plus(f), 1, !f.zero || (f.dot && !f.neg_prec)); 38 | else if (f.space) 39 | c += ft_putnchar_fd(' ', 1, !f.zero || f.dot); 40 | c += ft_putnchar_fd('0', 1, f.precision - len); 41 | c += write(1, nbr, len); 42 | if (f.minus && f.width > f.precision) 43 | c += ft_putnchar_fd(' ', 1, f.width - f.precision - neg - f.plus); 44 | return (c); 45 | } 46 | 47 | int ft_print_d_i_u(t_format f, va_list ap) 48 | { 49 | char *nbr; 50 | int n; 51 | int c; 52 | int len; 53 | int neg; 54 | 55 | c = 0; 56 | n = va_arg(ap, int); 57 | neg = (n < 0 && n != INT_MIN && f.specifier != 'u'); 58 | if (neg) 59 | f.plus = 0; 60 | if (n < 0 && f.specifier != 'u') 61 | n *= -1; 62 | if (n < 0 && f.specifier == 'u') 63 | nbr = ft_uitoa((unsigned)n); 64 | else 65 | nbr = ft_itoa(n); 66 | len = ft_strlen(nbr); 67 | if (*nbr == '0' && !f.precision && f.dot) 68 | len = 0; 69 | if (f.precision < len || !f.dot) 70 | f.precision = len; 71 | c += ft_print_nbr(f, nbr, len, neg); 72 | free(nbr); 73 | return (c); 74 | } 75 | -------------------------------------------------------------------------------- /src/ft_printf.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_printf.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/17 09:24:33 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 18:59:52 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | 15 | int ft_printf(const char *str, ...) 16 | { 17 | int count; 18 | va_list ap; 19 | char *first; 20 | 21 | count = 0; 22 | va_start(ap, str); 23 | while (*str) 24 | { 25 | if (*str == '%') 26 | { 27 | first = (char *)str; 28 | if (*(++str)) 29 | count += ft_parse((char *)str, ap); 30 | while (*str && !ft_strchr(SPECIFIERS, *str)) 31 | str++; 32 | if (!(*str)) 33 | str = first; 34 | } 35 | else 36 | count += ft_putchar_fd(*str, 1); 37 | if (*str) 38 | str++; 39 | } 40 | va_end(ap); 41 | return (count); 42 | } 43 | 44 | int ft_print_format(t_format f, va_list ap) 45 | { 46 | int count; 47 | 48 | count = 0; 49 | if (f.specifier == 'c' || f.specifier == '%') 50 | count = ft_print_c_pct(f, ap); 51 | if (f.specifier == 's') 52 | count = ft_print_s(f, ap); 53 | if (f.specifier == 'd' || f.specifier == 'i' || f.specifier == 'u') 54 | count = ft_print_d_i_u(f, ap); 55 | if (f.specifier == 'X' || f.specifier == 'x') 56 | count = ft_print_x(f, ap); 57 | if (f.specifier == 'p') 58 | count = ft_print_p(f, ap); 59 | return (count); 60 | } 61 | -------------------------------------------------------------------------------- /srcb/ft_format_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_format_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/21 08:52:18 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:31:31 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | t_format ft_newformat(void) 16 | { 17 | t_format newformat; 18 | 19 | newformat.minus = 0; 20 | newformat.plus = 0; 21 | newformat.width = 0; 22 | newformat.precision = 0; 23 | newformat.specifier = 0; 24 | newformat.zero = 0; 25 | newformat.dot = 0; 26 | newformat.space = 0; 27 | newformat.sharp = 0; 28 | newformat.neg_prec = 0; 29 | return (newformat); 30 | } 31 | -------------------------------------------------------------------------------- /srcb/ft_parse_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_parse_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/07/08 09:01:25 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:30:58 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | static t_format ft_parse_bonus(char *str, t_format f) 16 | { 17 | while (*str != '.' && !ft_strchr(SPECIFIERS, *str)) 18 | { 19 | if (*str == '+') 20 | f.plus = 1; 21 | if (*str == ' ') 22 | f.space = 1; 23 | if (*str == '#') 24 | f.sharp = 1; 25 | str++; 26 | } 27 | return (f); 28 | } 29 | 30 | static t_format ft_parse_width(char *str, va_list ap, t_format f) 31 | { 32 | int specified; 33 | 34 | specified = 0; 35 | while (*str != '.' && !ft_strchr(SPECIFIERS, *str)) 36 | { 37 | if (*str == '-') 38 | f.minus = 1; 39 | if (*str == '0' && !ft_isdigit(*(str - 1))) 40 | f.zero = 1; 41 | else if (((*str > '0' && *str <= '9') || *str == '*') && !specified) 42 | { 43 | if (*str == '*') 44 | f.width = va_arg(ap, int); 45 | else 46 | f.width = ft_atoi(str); 47 | specified = 1; 48 | } 49 | str++; 50 | } 51 | return (f); 52 | } 53 | 54 | static t_format ft_parse_precision(char *str, va_list ap, t_format f) 55 | { 56 | int specified; 57 | 58 | specified = 0; 59 | while (!ft_strchr(SPECIFIERS, *str)) 60 | { 61 | if ((ft_isdigit(*str) || *str == '*') && !specified) 62 | { 63 | if (*str == '*') 64 | f.precision = va_arg(ap, int); 65 | else 66 | f.precision = ft_atoi(str); 67 | specified = 1; 68 | } 69 | str++; 70 | } 71 | return (f); 72 | } 73 | 74 | int ft_parse(char *str, va_list ap) 75 | { 76 | t_format new_format; 77 | 78 | new_format = ft_parse_width(str, ap, ft_newformat()); 79 | new_format = ft_parse_bonus(str, new_format); 80 | while (!ft_strchr(SPECIFIERS, *str) && *str != '.') 81 | str++; 82 | if (*str == '.' && !new_format.specifier) 83 | { 84 | new_format.dot = 1; 85 | new_format = ft_parse_precision(str++, ap, new_format); 86 | while (!ft_strchr(SPECIFIERS, *str)) 87 | str++; 88 | } 89 | if (new_format.width < 0) 90 | { 91 | new_format.minus = 1; 92 | new_format.width *= -1; 93 | } 94 | new_format.specifier = *str; 95 | new_format.neg_prec = new_format.precision < 0; 96 | return (ft_print_format(new_format, ap)); 97 | } 98 | -------------------------------------------------------------------------------- /srcb/ft_print_chars_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_chars_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/22 10:43:07 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:32:44 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | int ft_print_c_pct(t_format f, va_list ap) 16 | { 17 | char c; 18 | int count; 19 | 20 | count = 0; 21 | if (f.specifier == 'c') 22 | c = va_arg(ap, int); 23 | else 24 | c = '%'; 25 | f.precision = 1; 26 | if (!f.minus && f.zero) 27 | count += ft_putnchar_fd('0', 1, f.width - f.precision); 28 | else if (!f.minus && f.width > f.precision) 29 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 30 | count += ft_putchar_fd(c, 1); 31 | if (f.minus && f.width - f.precision > 0) 32 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 33 | return (count); 34 | } 35 | 36 | int ft_print_s(t_format f, va_list ap) 37 | { 38 | char *string; 39 | int count; 40 | int has_malloc; 41 | 42 | count = 0; 43 | has_malloc = 0; 44 | string = va_arg(ap, char *); 45 | if (!string) 46 | { 47 | string = malloc(sizeof(char) * 7); 48 | has_malloc = 1; 49 | ft_strlcpy(string, "(null)", 7); 50 | } 51 | if (!f.dot || f.precision > (int)ft_strlen(string) || f.precision < 0) 52 | f.precision = ft_strlen(string); 53 | if (!f.minus && f.width > f.precision && f.zero && (!f.dot || f.neg_prec)) 54 | count += ft_putnchar_fd('0', 1, f.width - f.precision); 55 | else if (!f.minus && f.width - f.precision > 0) 56 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 57 | count += ft_putstrn_fd(string, 1, f.precision); 58 | if (f.minus && f.width - f.precision > 0) 59 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 60 | if (has_malloc) 61 | free(string); 62 | return (count); 63 | } 64 | -------------------------------------------------------------------------------- /srcb/ft_print_hex_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_hex_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/21 10:26:21 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:32:08 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | static char *ft_sharp(t_format f) 16 | { 17 | if (f.specifier == 'X') 18 | return ("0X"); 19 | return ("0x"); 20 | } 21 | 22 | static int ft_recursive_hex(t_format f, size_t n, size_t iteration) 23 | { 24 | int count; 25 | int remainder; 26 | char character; 27 | 28 | count = 0; 29 | if (n > 0 || (!iteration && (f.specifier != 'p' || !f.dot))) 30 | { 31 | remainder = n % 16; 32 | if (f.specifier != 'X') 33 | character = HEXALOW[remainder]; 34 | else 35 | character = HEXAUP[remainder]; 36 | n /= 16; 37 | iteration = 1; 38 | count += ft_recursive_hex(f, n, iteration); 39 | count += ft_putchar_fd(character, 1); 40 | } 41 | return (count); 42 | } 43 | 44 | int ft_print_x(t_format f, va_list ap) 45 | { 46 | int count; 47 | unsigned int n; 48 | int len; 49 | 50 | count = 0; 51 | n = va_arg(ap, unsigned int); 52 | len = ft_nbrlen(n, 16); 53 | if (!n && !f.precision && f.dot) 54 | len = 0; 55 | if (f.precision < 0 || f.precision < len || !f.dot) 56 | f.precision = len; 57 | if (f.sharp && n) 58 | f.width -= 2; 59 | count += ft_putstrn_fd(ft_sharp(f), 1, 2 * (f.sharp && f.zero && n)); 60 | if (!f.minus && f.width > f.precision && (!f.dot || f.neg_prec) && f.zero) 61 | count += ft_putnchar_fd('0', 1, (f.width - f.precision)); 62 | else if (!f.minus && f.width > f.precision) 63 | count += ft_putnchar_fd(' ', 1, (f.width - f.precision)); 64 | count += ft_putstrn_fd(ft_sharp(f), 1, 2 * (f.sharp && !f.zero && n)); 65 | count += ft_putnchar_fd('0', 1, (f.precision - len)); 66 | if (len) 67 | count += ft_recursive_hex(f, n, n); 68 | if (f.minus && f.width > f.precision) 69 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 70 | return (count); 71 | } 72 | 73 | int ft_print_p(t_format f, va_list ap) 74 | { 75 | int count; 76 | size_t n; 77 | int len; 78 | 79 | count = 0; 80 | n = va_arg(ap, size_t); 81 | len = ft_nbrlen(n, 16); 82 | len *= !(!n && !f.precision && f.dot); 83 | if (f.precision < len || !f.dot) 84 | f.precision = len; 85 | count += write(1, "0x", 2 * f.zero); 86 | f.width -= 2; 87 | if (!f.minus && f.width > f.precision && !f.dot && f.zero) 88 | count += ft_putnchar_fd('0', 1, (f.width - f.precision)); 89 | else if (!f.minus && f.width > f.precision) 90 | count += ft_putnchar_fd(' ', 1, (f.width - f.precision)); 91 | count += write(1, "0x", 2 * !f.zero); 92 | count += ft_putnchar_fd('0', 1, (f.precision - len) * (n != 0)); 93 | count += ft_putnchar_fd('0', 1, f.precision * (f.dot && !n)); 94 | if (len) 95 | count += ft_recursive_hex(f, n, n); 96 | if (f.minus && f.width > f.precision) 97 | count += ft_putnchar_fd(' ', 1, f.width - f.precision); 98 | return (count); 99 | } 100 | -------------------------------------------------------------------------------- /srcb/ft_print_nbrs_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_print_nbrs_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/22 09:58:43 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:33:23 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | static char plus(t_format f) 16 | { 17 | if (f.plus) 18 | return ('+'); 19 | return ('-'); 20 | } 21 | 22 | static int ft_print_nbr(t_format f, char *nbr, int len, int neg) 23 | { 24 | int c; 25 | 26 | c = 0; 27 | f.width -= (f.space && !neg && !f.plus && f.width); 28 | if (neg || f.plus) 29 | c += ft_putnchar_fd(plus(f), 1, f.zero && (!f.dot || f.neg_prec)); 30 | else if (f.space) 31 | c += ft_putnchar_fd(' ', 1, f.zero && !f.dot); 32 | if (!f.minus && f.width > f.precision && (!f.dot || f.neg_prec) && f.zero) 33 | c += ft_putnchar_fd('0', 1, f.width - f.precision - neg - f.plus); 34 | else if (!f.minus && f.width > f.precision) 35 | c += ft_putnchar_fd(' ', 1, f.width - f.precision - neg - f.plus); 36 | if (neg || f.plus) 37 | c += ft_putnchar_fd(plus(f), 1, !f.zero || (f.dot && !f.neg_prec)); 38 | else if (f.space) 39 | c += ft_putnchar_fd(' ', 1, !f.zero || f.dot); 40 | c += ft_putnchar_fd('0', 1, f.precision - len); 41 | c += write(1, nbr, len); 42 | if (f.minus && f.width > f.precision) 43 | c += ft_putnchar_fd(' ', 1, f.width - f.precision - neg - f.plus); 44 | return (c); 45 | } 46 | 47 | int ft_print_d_i_u(t_format f, va_list ap) 48 | { 49 | char *nbr; 50 | int n; 51 | int c; 52 | int len; 53 | int neg; 54 | 55 | c = 0; 56 | n = va_arg(ap, int); 57 | neg = (n < 0 && n != INT_MIN && f.specifier != 'u'); 58 | if (neg) 59 | f.plus = 0; 60 | if (n < 0 && f.specifier != 'u') 61 | n *= -1; 62 | if (n < 0 && f.specifier == 'u') 63 | nbr = ft_uitoa((unsigned)n); 64 | else 65 | nbr = ft_itoa(n); 66 | len = ft_strlen(nbr); 67 | if (*nbr == '0' && !f.precision && f.dot) 68 | len = 0; 69 | if (f.precision < len || !f.dot) 70 | f.precision = len; 71 | c += ft_print_nbr(f, nbr, len, neg); 72 | free(nbr); 73 | return (c); 74 | } 75 | -------------------------------------------------------------------------------- /srcb/ft_printf_bonus.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* ft_printf_bonus.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/17 09:24:33 by aperez-b #+# #+# */ 9 | /* Updated: 2021/09/27 19:31:55 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf_bonus.h" 14 | 15 | int ft_printf(const char *str, ...) 16 | { 17 | int count; 18 | va_list ap; 19 | char *first; 20 | 21 | count = 0; 22 | va_start(ap, str); 23 | while (*str) 24 | { 25 | if (*str == '%') 26 | { 27 | first = (char *)str; 28 | if (*(++str)) 29 | count += ft_parse((char *)str, ap); 30 | while (*str && !ft_strchr(SPECIFIERS, *str)) 31 | str++; 32 | if (!(*str)) 33 | str = first; 34 | } 35 | else 36 | count += ft_putchar_fd(*str, 1); 37 | if (*str) 38 | str++; 39 | } 40 | va_end(ap); 41 | return (count); 42 | } 43 | 44 | int ft_print_format(t_format f, va_list ap) 45 | { 46 | int count; 47 | 48 | count = 0; 49 | if (f.specifier == 'c' || f.specifier == '%') 50 | count = ft_print_c_pct(f, ap); 51 | if (f.specifier == 's') 52 | count = ft_print_s(f, ap); 53 | if (f.specifier == 'd' || f.specifier == 'i' || f.specifier == 'u') 54 | count = ft_print_d_i_u(f, ap); 55 | if (f.specifier == 'X' || f.specifier == 'x') 56 | count = ft_print_x(f, ap); 57 | if (f.specifier == 'p') 58 | count = ft_print_p(f, ap); 59 | return (count); 60 | } 61 | -------------------------------------------------------------------------------- /tests/main.c: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* main.c :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: aperez-b +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/04/17 09:37:37 by aperez-b #+# #+# */ 9 | /* Updated: 2021/10/16 11:52:20 by aperez-b ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #include "../inc/ft_printf.h" 14 | #include 15 | 16 | /* ******** Leaks ******** */ 17 | void check_leaks(int argc, char *uname) 18 | { 19 | if (!ft_strncmp(uname, "Linux", 5)) 20 | system("valgrind -q -s --leak-check=full --show-leak-kinds=all\ 21 | --track-origins=yes ./a.out"); 22 | else 23 | system("leaks a.out && ./a.out"); 24 | ft_printf("Finished checking leaks on %s!\n", uname); 25 | } 26 | 27 | int main(int argc, char **argv) 28 | { 29 | if (argc == 2) 30 | check_leaks(argc, argv[1]); 31 | else 32 | { 33 | printf("Len: %d\n", ft_printf("ft_printf: %p\n", &argc)); 34 | printf("Len: %d\n", printf("og_printf: %p\n", &argc)); 35 | } 36 | } 37 | --------------------------------------------------------------------------------