feat: Add `conversion/decimal_to_anybase.c` algorithm (#872)

* added Conversion/decimal_to_anybase.c

* Added Converstions/decimal_to_any_base.c

* Enhencement of decimal_to_any_base.c

* Update conversions/decimal_to_any_base.c

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update conversions/decimal_to_any_base.c

Co-authored-by: David Leal <halfpacho@gmail.com>

* updating DIRECTORY.md

* Update conversions/decimal_to_any_base.c

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update conversions/decimal_to_any_base.c

Co-authored-by: David Leal <halfpacho@gmail.com>

* text enhencement and debugging

* comments norming

* builtin int types declacration changed into arch optimized int types

* comments norming

* Adding booleans and int types normalization

* Translation of the program into a function and tests added

* Commentary rewriting in decimal_to_anybase and code beautify

* added 1 comments in main and code beautify

* Commentary norming

* Code norming

* Apply suggestions from code review

Co-authored-by: Votre Nom <Vous@exemple.com>
Co-authored-by: David Leal <halfpacho@gmail.com>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
AFK 2021-10-13 21:30:24 +02:00 committed by GitHub
parent 9d9bac2e9a
commit 2fd92f280d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 170 additions and 0 deletions

View File

@ -18,6 +18,7 @@
* [Binary To Hexadecimal](https://github.com/TheAlgorithms/C/blob/master/conversions/binary_to_hexadecimal.c)
* [Binary To Octal](https://github.com/TheAlgorithms/C/blob/master/conversions/binary_to_octal.c)
* [C Atoi Str To Integer](https://github.com/TheAlgorithms/C/blob/master/conversions/c_atoi_str_to_integer.c)
* [Decimal To Any Base](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_any_base.c)
* [Decimal To Binary](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_binary.c)
* [Decimal To Binary Recursion](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_binary_recursion.c)
* [Decimal To Hexa](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_hexa.c)

View File

@ -0,0 +1,169 @@
/**
* @file
* @author [jucollet972](https://github.com/jucollet972)
* @brief [Decimal to any-base](http://codeofthedamned.com/index.php/number-base-conversion) is a C function wich convert positive decimal
* integer to any positive ascii base with the base's alphabet given in input and return it in a dynamically allocated string(recursive way)
*/
#include <stdio.h> /// for IO operations
#include <string.h> /// for strchr and strlen
#include <stdint.h> /// for CPU arch's optimized int types
#include <stdbool.h> /// for boolean types
#include <assert.h> /// for assert
#include <stdlib.h> /// for malloc and free
/**
* @brief Checking if alphabet is valid
* @param base alphabet inputed by user
* @return int64_t as success or not
*/
bool isbad_alphabet(const char* alphabet) {
uint64_t len = strlen(alphabet);
/* Checking th lenght */
if (len < 2) {
return true;
}
/* Browse the alphabet */
for (int i = 0; i < len ; i++) {
/* Searching for duplicates */
if (strchr(alphabet + i + 1, alphabet[i]))
return true;
}
return false;
}
/**
* @brief Calculate the final length of the converted number
* @param nb to convert
* @param base calculated from alphabet
* @return Converted nb string length
*/
uint64_t converted_len(uint64_t nb, short base) {
/* Counting the number of characters translated to the base*/
if (nb > base - 1) {
return (converted_len(nb/base, base) + 1);
}
return 1;
}
/**
* @brief Convert positive decimal integer into anybase recursively
* @param nb to convert
* @param alphabet inputed by user used for base convertion
* @param base calculated from alphabet
* @param converted string filled with the convertion's result
* @return void
*/
void convertion(uint64_t nb, const char* alphabet, short base, char* converted) {
/* Recursive convertion */
*(converted) = *(alphabet + nb%base);
if (nb > base - 1) {
convertion(nb/base, alphabet, base, --converted);
}
}
/**
* @brief decimal_to_anybase ensure the validity of the parameters and convert any unsigned integers into any ascii positive base
* @param nb to convert
* @param base's alphabet
* @returns nb converted on success
* @returns NULL on error
*/
char* decimal_to_anybase(uint64_t nb, const char* alphabet) {
char* converted;
/* Verify that alphabet is valid */
if (isbad_alphabet(alphabet)) {
return NULL;
}
/* Convertion */
uint64_t base = strlen(alphabet);
uint64_t final_len = converted_len(nb, base);
converted = malloc(sizeof(char) * (final_len + 1));
converted[final_len] = 0;
convertion(nb, alphabet, base, converted + final_len - 1);
return converted;
}
/**
* @brief Self-test implementations
* @returns void
*/
static void test()
{
char* ret = NULL;
char* reference = NULL;
/* min dec*/
reference = "0";
ret = decimal_to_anybase(0, "0123456789");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
/* max dec*/
reference = "18446744073709551615";
ret = decimal_to_anybase(18446744073709551615, "0123456789");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
/* negative dec*/
reference = "18446744073709551615";
ret = decimal_to_anybase(-1, "0123456789");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
/* bin */
reference = "101010";
ret = decimal_to_anybase(42, "01");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
/* octal */
reference = "52";
ret = decimal_to_anybase(42, "01234567");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
/* hexa */
reference = "2A";
ret = decimal_to_anybase(42, "0123456789ABCDEF");
for (int i = 0; i < strlen(reference) && i < strlen(ret); i++) {
assert(ret[i] == reference[i]);
}
if (ret != NULL) {
free(ret);
}
printf("[+] All tests have successfully passed!\n");
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main()
{
test(); // run self-test implementations
return 0;
}