diff --git a/ft_printf.c b/ft_printf.c index 660f555..418a516 100644 --- a/ft_printf.c +++ b/ft_printf.c @@ -81,26 +81,36 @@ int ft_expand_star(int nbr, char **string) ** because of lake of space, it also free 'type' */ -int ft_put_word(char *s, char *type) +int ft_put_word(char *s, char *type, int size) { int i; + i = 0; + while (i < size) + write(1, &(s[i++]), 1); free(type); - i = ft_strlen(s); - ft_putstr(s); free(s); return (i); } /* -** print the string -** because of lake of space, it also free 'type' +** because of lake of space... +** -1 expand the specifier according to its type and its length +** and put in a string 'print' +** -2 transform 'print' according to the flags */ -int length_n_free(int length, char *s) +char *convert_with_flags(char *s, va_list ap, char *type, int *size) { + char *print; + + if (!(print = ft_convert(ap, type, &s))) + return (NULL); + if (!(print = ft_flag_transform(s, print, type, size))) + return (NULL); free(s); - return (length); + s = print; + return(print); } /* @@ -108,21 +118,18 @@ int length_n_free(int length, char *s) ** -it will go in a loop through each 'words' ** -a word is either a string containing no '%' or a conversion starting by '%' ** -if it's a string it's printed right away -** -if it's a conversion it will go through some actions : -** -1 expand all the stars from width and .precision -** they always expand into int type -** it's done first because those are the first next args on the va_list -** -2 expand the specifier according to its type and its length +** -if it's a conversion it will call convert_with_flags for some actions : +** -1 expand the specifier according to its type and its length ** and put in a string 'print' -** -3 transform 'print' according to the flags +** -2 transform 'print' according to the flags */ int ft_printf(char *string, ...) { char *s; - char *print; char *type; int length; + int size; va_list ap; length = 0; @@ -130,18 +137,15 @@ int ft_printf(char *string, ...) while ((s = next_word(&string)) != NULL) { if ((type = specifier(s)) == NULL) - length += ft_put_word(s, type); + length += ft_put_word(s, type, ft_strlen(s)); else { - while (ft_strchr(s, '*')) - if (!(ft_expand_star(va_arg(ap, int), &s))) - return (-1); - if (!(print = ft_convert(ap, type))) + size = 0; + if (!(s = convert_with_flags(s, ap, type, &size))) return (-1); - if (!(print = ft_flag_transform(s, print, type))) - return (-1); - length += ft_put_word(print, type); + length += ft_put_word(s, type, size); } } - return (length_n_free(length, s)); + free(s); + return (length); } diff --git a/ft_printf.h b/ft_printf.h index f0c7d3f..87c02b5 100644 --- a/ft_printf.h +++ b/ft_printf.h @@ -25,8 +25,8 @@ char *specifier(char *s); int ft_expand_star(int nbr, char **string); -int ft_put_word(char *s, char *type); -int length_n_free(int length, char *s); +int ft_put_word(char *s, char *type, int size); +char *convert_with_flags(char *s, va_list ap, char *type, int *size); int ft_printf(char *string, ...); /* @@ -43,7 +43,7 @@ char *next_word(char **s); char *conv_i(char c, long int i); char *conv_u(char c, unsigned long int i); -char *ft_convert(va_list ap, char *type); +char *ft_convert(va_list ap, char *type, char **s); /* ** ft_flag_transform.c @@ -51,8 +51,8 @@ char *ft_convert(va_list ap, char *type); char *precision_int(char *print, int precision); char *ft_precision(char *s, char *print, char *type); -char *width_flags(char *print, char *tmp, char *s, int width); -char *ft_width(char *s, char *print); -char *ft_flag_transform(char *s, char *print, char *type); +char *width_flags(char *print, char *tmp, char *s, int width, int zero); +char *ft_width(char *s, char *print, int *size); +char *ft_flag_transform(char *s, char *print, char *type, int *size); #endif diff --git a/main.c b/main.c index 850caa2..2c44193 100644 --- a/main.c +++ b/main.c @@ -10,42 +10,42 @@ // then the result of ft_printf, // and finally redirect the output into a file to compare #define PRINT(string, args...) \ - outf = open("outf.txt", O_WRONLY | O_TRUNC); \ - outft = open("outft.txt", O_WRONLY | O_TRUNC); \ - \ - dup2(outf, 1); \ - printf(string "\n", ##args); \ - fflush(stdout); \ - \ - dup2(outft, 1); \ - if ((ft_printf(string, ##args)) == -1) printf("\033[91mERROR\033[0m"); \ - fflush(stdout); \ - printf("\n"); \ - fflush(stdout); \ - \ - close(outf); \ - close(outft); \ - outf = open("outf.txt", O_RDONLY); \ - outft = open("outft.txt", O_RDONLY); \ - \ - dup2(save, 1); \ - printf("(%s, %s)", #string, #args); \ - fflush(stdout); \ - printf("%*s", (int)(40 - ft_strlen(#string) - ft_strlen(#args)), ": "); \ - fflush(stdout); \ - printf("'" string "'\n", ##args); \ - fflush(stdout); \ - printf("%s", ft_compare(outf, outft, &error)); \ - fflush(stdout); \ - printf("%38s", ": '"); \ - fflush(stdout); \ - if ((ft_printf(string, ##args)) == -1) printf("\033[91mERROR\033[0m"); \ - fflush(stdout); \ - printf("'\n\n"); \ - fflush(stdout); \ - \ - close(outf); \ - close(outft); + outf = open("outf.txt", O_WRONLY | O_TRUNC); \ + outft = open("outft.txt", O_WRONLY | O_TRUNC); \ + \ + dup2(outf, 1); \ + printf(string "\n", ##args); \ + fflush(stdout); \ + \ + dup2(outft, 1); \ + if ((ft_printf(string, ##args)) == -1) printf("\033[91mERROR\033[0m"); \ + fflush(stdout); \ + printf("\n"); \ + fflush(stdout); \ + \ + close(outf); \ + close(outft); \ + outf = open("outf.txt", O_RDONLY); \ + outft = open("outft.txt", O_RDONLY); \ + \ + dup2(save, 1); \ + printf("(%s, %s)", #string, #args); \ + fflush(stdout); \ + printf("%*s", (int)(40 - ft_strlen(#string) - ft_strlen(#args)), ": "); \ + fflush(stdout); \ + printf("'" string "'\n", ##args); \ + fflush(stdout); \ + printf("%s", ft_compare(outf, outft, &error)); \ + fflush(stdout); \ + printf("%38s", ": '"); \ + fflush(stdout); \ + if ((ft_printf(string, ##args)) == -1) printf("\033[91mERROR\033[0m"); \ + fflush(stdout); \ + printf("'\n\n"); \ + fflush(stdout); \ + \ + close(outf); \ + close(outft); /* ** this fucntion look into the two files outf.txt and outft.txt in which diff --git a/outf.txt b/outf.txt index 275e73e..5c94524 100644 Binary files a/outf.txt and b/outf.txt differ diff --git a/outft.txt b/outft.txt index d88260b..5c94524 100644 --- a/outft.txt +++ b/outft.txt @@ -1 +1 @@ -! ! +33333 diff --git a/srcs/ft_convert.c b/srcs/ft_convert.c index f2090fa..0af8cb9 100644 --- a/srcs/ft_convert.c +++ b/srcs/ft_convert.c @@ -58,6 +58,9 @@ char *conv_u(char c, unsigned long int i) } /* +** -first a loop to expand all the stars from width and .precision +** they always expand into int type +** it's done first because those are the first next args on the va_list ** -for each kind of specifier there is finally four kinds of conversion : ** int / long int / unsigned int / unsingned long int ** -the conversion 'uxX' associated with 'l' are converted with lu, but @@ -68,18 +71,21 @@ char *conv_u(char c, unsigned long int i) ** or for 'p' and again for 'p', or 's' twice similarly */ -char *ft_convert(va_list ap, char *type) +char *ft_convert(va_list ap, char *type, char **s) { - char *s; + char *tmp; - if ((s = ft_strchrset(type, "dic")) && ft_strchr(type, 'l')) - return (conv_i(s[0], va_arg(ap, long int))); - if ((s = ft_strchrset(type, "dic"))) - return (conv_i(s[0], va_arg(ap, int))); - if ((s = ft_strchrset(type, "uxXps")) && ft_strchrset(type, "lps")) - return (conv_u(s[0], va_arg(ap, unsigned long int))); - if ((s = ft_strchrset(type, "uxX"))) - return (conv_u(s[0], va_arg(ap, unsigned int))); + while (ft_strchr(*s, '*')) + if (!(ft_expand_star(va_arg(ap, int), s))) + return (NULL); + if ((tmp = ft_strchrset(type, "dic")) && ft_strchr(type, 'l')) + return (conv_i(tmp[0], va_arg(ap, long int))); + if ((tmp = ft_strchrset(type, "dic"))) + return (conv_i(tmp[0], va_arg(ap, int))); + if ((tmp = ft_strchrset(type, "uxXps")) && ft_strchrset(type, "lps")) + return (conv_u(tmp[0], va_arg(ap, unsigned long int))); + if ((tmp = ft_strchrset(type, "uxX"))) + return (conv_u(tmp[0], va_arg(ap, unsigned int))); if (ft_strchr(type, '%')) return (ft_strdup("%")); if (ft_strchrset(type, "efgn")) diff --git a/srcs/ft_flag_transform.c b/srcs/ft_flag_transform.c index c87541b..9faa8f0 100644 --- a/srcs/ft_flag_transform.c +++ b/srcs/ft_flag_transform.c @@ -91,7 +91,7 @@ char *ft_precision(char *s, char *print, char *type) ** -else, put extra width as ' ' to left of 'print' */ -char *width_flags(char *print, char *tmp, char *s, int width) +char *width_flags(char *print, char *tmp, char *s, int width, int zero) { char c; int i; @@ -101,6 +101,8 @@ char *width_flags(char *print, char *tmp, char *s, int width) j = 0; if (ft_strchr(s, '-')) { + if (print[j] == '\0') + tmp[i++] = '\0'; while (print[j] != '\0') tmp[i++] = print[j++]; while (i < width) @@ -109,8 +111,10 @@ char *width_flags(char *print, char *tmp, char *s, int width) else { c = (ft_strchr(s, '0')) ? '0' : ' '; - while (i < (width - ft_strlen(print))) + while (i < (width - ft_strlen(print) - zero)) tmp[i++] = c; + if (print[j] == '\0') + tmp[i++] = '\0'; while (print[j] != '\0') tmp[i++] = print[j++]; } @@ -121,30 +125,41 @@ char *width_flags(char *print, char *tmp, char *s, int width) /* ** -if there is a minimal width field, calculate it and add it to print ** according to the flags '-' and '0' if present -** -if print[0] value 0 +** -in details : +** 1 loop through s, the string starting by '%' and ending by a converter, +** until it has passed all the flags that are not a potentiel width field +** 2 then if it's the end of s, there is no width and print isn't changed, +** otherwise the int 'width' take the value returned by atoi +** 3 if print[0] value 0, as it happens for type c with (char)0, */ -char *ft_width(char *s, char *print) +char *ft_width(char *s, char *print, int *size) { char *tmp; - int width; + int zero; tmp = s; + zero = 0; while (*tmp != '\0' && ft_strchr("%#- +'0.", *tmp)) tmp++; if (*tmp == '\0') + { + *size = ft_strlen(print); return (print); - width = ft_atoi(tmp); + } + *size = ft_atoi(tmp); tmp[0] = '\0'; if (print[0] == '\0') - width--; - if (width > ft_strlen(print)) + zero = 1; + if (*size > ft_strlen(print) + zero) { - if (!(tmp = (char *)malloc(sizeof(char) * (width + 1)))) + if (!(tmp = (char *)malloc(sizeof(char) * (*size + 1)))) return (NULL); - tmp[width] = '\0'; - print = width_flags(print, tmp, s, width); + tmp[*size] = '\0'; + print = width_flags(print, tmp, s, *size, zero); } + else + *size = ft_strlen(print); return (print); } @@ -153,11 +168,14 @@ char *ft_width(char *s, char *print) ** -the case of 'p' is treated without any subtelness because i don't care */ -char *ft_flag_transform(char *s, char *print, char *type) +char *ft_flag_transform(char *s, char *print, char *type, int *size) { print = ft_precision(s, print, type); - print = ft_width(s, print); + print = ft_width(s, print, size); if (ft_strchr(type, 'p')) + { print = ft_concat_free(ft_strdup("0x"), print); + *size += 2; + } return (print); }