ft_print.c now conforms to the Norm (except function number).
authorLukas Jiriste <ljiriste@student.42prague.com>
Sat, 26 Aug 2023 05:59:25 +0000 (07:59 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Sat, 26 Aug 2023 05:59:25 +0000 (07:59 +0200)
Not all functionality is yet provided (notably %%, other need to be found by testing).
New version of Libft is used.

Libft
ft_printf.c

diff --git a/Libft b/Libft
index 176dfd9fd936e853cf87239219416ee774602dcf..5b3c0fcbf58c6458fcd10d2ad48c9f698ce7a8c8 160000 (submodule)
--- a/Libft
+++ b/Libft
@@ -1 +1 @@
-Subproject commit 176dfd9fd936e853cf87239219416ee774602dcf
+Subproject commit 5b3c0fcbf58c6458fcd10d2ad48c9f698ce7a8c8
index 9946fb097d690fc73fb4afe0776de67abfe8b6d3..ef106dea1f24a85bd0bca4ebc39bbe7d7aab27cd 100644 (file)
@@ -10,8 +10,8 @@
 /*                                                                            */
 /* ************************************************************************** */
 
-#include <stdlib.h>    // malloc, free
-#include <stdarg.h>    // va_*
+#include <stdlib.h>            // malloc, free
+#include <stdarg.h>            // va_*
 #include <unistd.h>    // write
 #include "libft.h"
 
@@ -27,7 +27,7 @@ int   print_ordinary(const char **s)
        return (len);
 }
 
-typedef        struct s_flags
+typedef struct s_flags
 {
        int     alt_mode;
        int     zero_pad;
@@ -36,7 +36,7 @@ typedef       struct s_flags
        int     sign_show;
 }              t_flags;
 
-typedef        struct s_conv
+typedef struct s_conv
 {
        t_flags flags;
        int             minwidth;
@@ -52,7 +52,7 @@ t_flags       parse_flags(const char **format)
        flags.zero_pad = 0;
        flags.left_adjust = 0;
        flags.sign_allign = 0;
-       flags.sign_show = 0;    
+       flags.sign_show = 0;
        while (1)
        {
                if (**format == '#')
@@ -128,11 +128,18 @@ int       valid_base(const char *base)
        return (1);
 }
 
+intptr_t       ft_abs(intptr_t n)
+{
+       if (n < 0)
+               return (-n);
+       else
+               return (n);
+}
 
 char   *ft_itoa_base(intptr_t n, const char *base)
 {
        int             size;
-       size_t  base_len;
+       int             base_len;
        char    *res;
 
        if (!valid_base(base))
@@ -147,7 +154,7 @@ char        *ft_itoa_base(intptr_t n, const char *base)
        res[size--] = '\0';
        while (n != 0)
        {
-               res[size--] = base[abs(n % base_len)];
+               res[size--] = base[ft_abs(n % base_len)];
                n /= base_len;
        }
        return (res);
@@ -206,7 +213,7 @@ t_conv      parse_format(const char **format, va_list *args)
        return (conv);
 }
 
-typedef struct s_printed
+typedef struct s_to_print
 {
        char    *left_pad;
        char    sign;
@@ -214,13 +221,13 @@ typedef struct s_printed
        char    *zero_pad;
        char    *main_part;
        char    *right_pad;
-}                      t_printed;
+}                      t_to_print;
 
 char   *create_alt(t_conv conv)
 {
        if (conv.type == 'p')
                return (ft_strdup("0x"));
-       else if (conv.flag.alt_mode)
+       else if (conv.flags.alt_mode)
        {
                if (conv.type == 'o')
                        return (ft_strdup("0"));
@@ -234,7 +241,7 @@ char        *create_alt(t_conv conv)
 
 void   create_main(char *str, t_conv conv, t_to_print *tp)
 {
-       if  (conv.type == 'd' || conv.type == 'i')
+       if (conv.type == 'd' || conv.type == 'i')
        {
                if (*str == '-')
                {
@@ -243,40 +250,129 @@ void     create_main(char *str, t_conv conv, t_to_print *tp)
                }
                else
                {
-                       tp->main_part = ft_strfup(str);
+                       tp->main_part = ft_strdup(str);
                        if (conv.flags.sign_show)
                                tp->sign = '+';
                        else if (conv.flags.sign_allign)
                                tp->sign = ' ';
                }
        }
-       else if (conv.type == 's' && conv.prec < ft_strlen(str))
+       else if (conv.type == 's'
+               && (size_t)conv.prec < ft_strlen(str) && conv.prec >= 0)
+               tp->main_part = ft_strndup(str, conv.prec);
+       else
+               tp->main_part = ft_strdup(str);
+       return ;
+}
+
+void   init_printed(t_to_print *tp)
+{
+       tp->left_pad = NULL;
+       tp->sign = '\0';
+       tp->zero_pad = NULL;
+       tp->main_part = NULL;
+       tp->right_pad = NULL;
+       return ;
+}
+
+char   *rep_char(char c, int n)
+{
+       char    *res;
+
+       if (n < 0)
+               n = 0;
+       res = malloc(++n);
+       if (res == NULL)
+               return (res);
+       res[--n] = '\0';
+       while (n > 0)
+               res[--n] = c;
+       return (res);
+}
+
+void   lengthen_by_zeros(char **str, int n)
+{
+       char    *temp;
+       size_t  size;
+
+       if (n <= 0)
+               return ;
+       temp = *str;
+       size = ft_strlen(temp) + n + 1;
+       *str = malloc(size);
+       if (*str == NULL)
        {
-               tp->main_part = malloc((conv.prec + 1) * sizeof(char));
-               if (tp.main_part == NULL)
-                       return ();
-               ft_strlcpy(tp->main_part, str, conv.prec + 1);
+               free(temp);
+               return ;
+       }
+       ft_strlcpy(*str, temp, size);
+       free(temp);
+       while (n > 0)
+               (*str)[size - (n--) - 1] = '0';
+       (*str)[size - 1] = '\0';
+       return ;
+}
+
+void   create_padding(t_to_print *tp, t_conv conv)
+{
+       size_t  len;
+
+       len = ft_strlen(tp->main_part);
+       tp->zero_pad = rep_char('0', conv.prec - len);
+       len += ft_strlen(tp->zero_pad) + ft_strlen(tp->alt) + (tp->sign != '\0');
+       if (conv.flags.left_adjust)
+       {
+               tp->right_pad = rep_char(' ', conv.minwidth - len);
+               tp->left_pad = ft_strdup("");
        }
        else
-               tp->main_part = ft_strdup(str);
-       return ();
+       {
+               tp->right_pad = ft_strdup("");
+               if (!conv.flags.zero_pad || conv.type == 's')
+                       tp->left_pad = rep_char(' ', conv.minwidth - len);
+               else if (conv.flags.zero_pad)
+               {
+                       tp->left_pad = ft_strdup("");
+                       lengthen_by_zeros(&(tp->zero_pad), conv.minwidth - len);
+               }
+       }
+       return ;
 }
 
-t_printed      formated(char *str, t_conv conv)
+t_to_print     formated(char *str, t_conv conv)
 {
        t_to_print      res;
 
        init_printed(&res);
        create_main(str, conv, &res);
        res.alt = create_alt(conv);
-       
+       create_padding(&res, conv);
+       return (res);
+}
+
+int    valid_toprint(t_to_print tp)
+{
+       return (tp.left_pad && tp.zero_pad && tp.main_part && tp.right_pad);
+}
+
+size_t to_print_len(t_to_print tp)
+{
+       size_t  len;
+
+       len = 0;
+       len += ft_strlen(tp.left_pad);
+       len += (tp.sign != '\0');
+       len += ft_strlen(tp.alt);
+       len += ft_strlen(tp.zero_pad);
+       len += ft_strlen(tp.main_part);
+       len += ft_strlen(tp.right_pad);
+       return (len);
 }
 
 int    handle_conversion(const char **format, va_list *args)
 {
        t_conv          conv;
-       char            *str;
-       int                     len;
+       char            *temp;
        t_to_print      to_print;
 
        ++(*format);
@@ -292,7 +388,7 @@ int handle_conversion(const char **format, va_list *args)
        ft_putstr_fd(to_print.alt, 1);
        ft_putstr_fd(to_print.main_part, 1);
        ft_putstr_fd(to_print.right_pad, 1);
-       return (len);
+       return (to_print_len(to_print));
 }
 
 int    ft_printf(const char *format, ...)
@@ -300,12 +396,13 @@ int       ft_printf(const char *format, ...)
        va_list args;
        int             res;
 
+       res = 0;
        va_start(args, format);
        while (*format)
        {
                res += print_ordinary(&format);
                if (!*format)
-                       break;
+                       break ;
                res += handle_conversion(&format, &args);
        }
        va_end(args);