diff --git a/.gitignore b/.gitignore index 088e750..844aedb 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,8 @@ dkms.conf # OS generated files # *.swp +*.swo +*.~ .DS_Store .DS_Store? ._* diff --git a/srcs/ft_convertbase.c b/srcs/ft_convertbase.c index a934e81..a11fe5c 100644 --- a/srcs/ft_convertbase.c +++ b/srcs/ft_convertbase.c @@ -1,86 +1,159 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ft_convertbase.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: hulamy +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2018/11/16 15:15:55 by hulamy #+# #+# */ -/* Updated: 2020/02/19 18:47:35 by hulamy ### ########.fr */ -/* */ -/* ************************************************************************** */ +/* +** take a string that is a number in a certain and convert it in another base +** return the new string +*/ + + + #include // for printf + #include // for atoi + + char *ft_convertbase(char *nbr, char *base_from, char *base_to); + + int main(int ac, char **av) + { + if (ac != 4) + printf("usage:\nchar *nbr, char *base_from, char *base_to\ntry the max long unsigned int : 9223372036854775807"); + else + printf("[%s]\n",ft_convertbase(av[1], av[2], av[3])); + return (0); + } + #include "libft.h" -static int ft_malloc_size(int decimal, int length, int i) -{ - if (decimal <= 0) - i++; - while (decimal) - { - decimal /= length; - i++; - } - return (i); -} +/* +** check : +** -if the base has no characters that appear more than one time +** -if the signes '-' and '+' are not part of the set +** -if there are no invisible characters (inferior to 32 or equal to 127) +*/ -static char *ft_decimal_to_base(int decimal, char *base, char *res, int size) +int + is_valid_base(char *base) { - long nb; - int i; + int i; + int j; - nb = decimal; i = 0; while (base[i]) - i++; - if (nb < 0) - nb = -nb; - while (--size >= 0) { - res[size] = base[nb % i]; - nb /= i; + j = i + 1; + while (base[j]) + if (base[i] == base[j++]) + return (0); + if (base[i] == '-' || base[i] == '+' || base[i] < 33 || base[i] == 127) + return (0); + i++; } - return (res); + if (i >= 2) + return (1); + return (0); } -static int ft_base_to_decimal(char *nbr, char *base, int length, int i) +/* +** check : +** -if base is valid +** -if nbr contain characters +** -if nbr is made of elements of base only +*/ + +int + is_valid_nbr(char *nbr, char *base) { - long decimal; - int j; + int i; + int j; + + i = 0; + if (!is_valid_base(base)) + return (0); + while (nbr[i]) + { + j = 0; + while (base[j] && nbr[i] != base[j]) + j++; + if (base[j] == '\0') + return (0); + i++; + } + if (i == 0) + return (0); + return (1); +} + +/* +** -transform a nbr written as a string into a decimal nbr +** -it's an unsigned nbr because the negativity is managed elsewhere +** -if the number is bigger than the max unsigned long int it's false +*/ + +unsigned long int + base_to_decimal(char *nbr, char *base) +{ + unsigned long int decimal; + int i; + int j; + int length; decimal = 0; - if (nbr[i] == '-') - i++; + i = 0; + length = 0; + while (base[length]) + length++; while (nbr[i]) { j = 0; while (nbr[i] != base[j] && base[j]) j++; + if ((18446744073709551615U - j) / length > decimal) + return (0); decimal = (decimal * length) + j; i++; } - if (nbr[0] == '-') - decimal = -decimal; return (decimal); } -char *ft_convertbase(char *nbr, char *base_from, char *base_to) +char + *decimal_to_base(unsigned long int decimal, char *base, int malloc_size) { - int length; - int size; - int decimal; - char *res; + int base_size; + int neg; + char *result; + unsigned long int nb; - res = 0; - length = 0; - while (base_from[length]) - length++; - decimal = ft_base_to_decimal(nbr, base_from, length, 0); - length = 0; - while (base_to[length]) - length++; - size = ft_malloc_size(decimal, length, 0); - res = (char *)malloc(sizeof(char) * (size + 1)); - res[size] = '\0'; - return (ft_decimal_to_base(decimal, base_to, res, size)); + neg = malloc_size; + base_size = 0; + while (base[base_size]) + base_size++; + nb = decimal; + while (nb /= base_size) + malloc_size++; + result = (char *)malloc(sizeof(char) * (malloc_size + 2)); + result[malloc_size + 1] = '\0'; + if (neg) + result[0] = '-'; + while (malloc_size >= 0) + { + result[malloc_size--] = base[decimal % base_size]; + decimal /= base_size; + } + return (result); +} + +char + *ft_convertbase(char *nbr, char *base_from, char *base_to) +{ + int length; + unsigned long int decimal; + + length = 0; + if (nbr[0] == '-') + { + nbr++; + length = 1; + } + if (!is_valid_nbr(nbr, base_from) || !is_valid_base(base_to)) + return (NULL); + if ((decimal = base_to_decimal(nbr, base_from)) == 0) + return (NULL); + return (decimal_to_base(decimal, base_to, length)); }