4
\$\begingroup\$

I'm a beginner and tried to make a decimal to any base converter using C and I plan to upgrade it to an any base to any base converter.

This is my code: (questions at the bottom)

#include <stdio.h>
#include <stdlib.h>

//DECIMAL TO ANY BASE

void decIntTAB();
void decFraTAB();
int digitCount();
void printOut();

int main()
{
    printf("\t\t\t\t\tBASIC NUMBER CONVERSIONS\n\n");
    printf("Base Guide: \t\t2 - Binary \t\t8 - Octal \t\t10 - Decimal \t\t16 - Hexadecimal\n\n");

    char input[150];
    double temp;
    int base;

    printf("Input decimal: ");
    scanf("%s", input);
    printf("Convert to base: ");
    scanf("%d", &base);

    printf("\n\n");

    if(sscanf(input, "%lf", &temp)==1){
        if((int)temp-temp!=0){//integer input minus original input, if it is not 0, it is a float
            int decimalInt=(int)temp;
            double decimalFlt=temp-decimalInt;

            decIntTAB(decimalInt,base);
            printf(".");
            decFraTAB(decimalFlt, base);
        }else{ //integer
            int decimalInt=(int)temp;
            decIntTAB(decimalInt, base);
        }
    }else{
        printf("Invalid Input");
    }

    printf("\n\n");
    return 0;
}


int digitCount(int input, int base){//counts digit to be used in array in decimal integer conversion
    int rem;
    int digit=0;

    while(input>0){
            rem=input%base;
            input=input/base;
            digit++;
        }
    return digit;
}

void printOut(int x){//PRINTS OUT ALL DIGITS; INCLUDES HEXADECIMAL CONVERT; input INTEGER to print
    char hex[6]="ABCDEF";
    int hexCheck=10;

    if(x>10){//if answer is 10 above print as ABCDEF
        for(int n=0;n<=6;n++){
            if(x==hexCheck){
                printf("%c", hex[n]);
                break;
            }else{
                hexCheck++;
            }
        }
    }else{
        printf("%d", x);//if answer is 9 below print as is
    }
}

void decIntTAB(int input, int base){ //performs decimal integer to any base; input INPUT and BASE
    int rem;

    //COUNTS NUMBER OF DIGITS TO BE USED IN ARRAY
    int digit=digitCount(input, base);

    int array[digit];

    //MATH PROCESS
    for(int a=(digit-1);a>=0;a--){ //assigns remainder/answer in reverse (since first answer is least significant)
        rem=input%base;
        array[a]=rem;
        input=input/base;
    }

    for(int b=0;b<=(digit-1);b++){//Prints out array
        printOut(array[b]);
    }
}

void decFraTAB(double input, int base){
    while (input>0){
        input=input*base;
        int temp=(int)input;
        printOut(temp);
        input=input-temp;//sets input to be input(in fractional form) minus temp(input's integer value) to isolate fractional value
    }

}

  • Is there any way to better, shorten or optimize my code?
  • To convert an integer decimal to any base, I use this equation where the result should be reversed. At first I tried to do that by doing the equation without printing or saving the result to count (digitCount() function) how many times it loops so I can use that count to make an array where I would redo the equation, this time saving the values in an array in reverse. Thing is, I realized just now that I could do it with the code below as well with having to make a digitCount() function, only I'll just have to make an int array with a pretty big number (int array[200]). Code:
void decIntTAB(int input, int base){ //performs decimal integer to any base; input INPUT and BASE
    int rem;
    int array[200];
    int digit=0;
    //MATH PROCESS

    while(rem>=0){
        rem=input%base;
        array[digit]=rem;//Puts value in array from left to right (index 0 to maximum)
        input=input/base;
        digit++;
    }

    for(int a=(digit-1);a>=0;a--){//Prints out array from right to left (index maximum to 0)
        printOut(array[a]);
    }
}
  • Would this be a better alternative to having to make a separate function like my digitCount()?
  • Can you give me other tips to make this code better or maybe if there's some function in C that I'm not aware of that could replace something in my code?

Thanks!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ your function signatures do not match the actual function code. \$\endgroup\$
    – hjpotter92
    Dec 16 '20 at 4:14
  • 1
    \$\begingroup\$ You might want to look at the source code for library implementations of strtol, which does exactly what you want. \$\endgroup\$
    – Lundin
    Dec 16 '20 at 7:10
3
\$\begingroup\$

Bug (conversion)

When double temp is well outside the int range, (int)temp is undefined behavior (UB).

    if((int)temp-temp!=0){

Instead use modf() to returns the fractional portion of temp.

    double whole;
    if (modf(temp, &whole) != 0.0) {

Insufficient buffer

char input[150]; seems small for "a decimal to any base converter" as DBL_MAX is often a 309 base-10 digit, 1024 base-2 value.

Yet it looks like code is attempting only an int range conversion. A buffer size of sizeof(int) * CHAR_BIT + a_few should suffice.

\$\endgroup\$
1
\$\begingroup\$
void decIntTAB();
void decFraTAB();
int digitCount();
void printOut();

Prefer to make these declarations prototypes - i.e. include the arguments so that the compiler can confirm that they are called correctly.

printf("Input decimal: ");
scanf("%s", input);
printf("Convert to base: ");
scanf("%d", &base);

scanf() can fail (so can printf(), but that's less serious). We really don't want to continue if that happens, so check the return value! Also, flush output before reading input, so that the user definitely gets the prompt.

scanf("%s", input);

This line is particularly dangerous, as we haven't limited the maximum input size to what will fit in input.

scanf("%d", &base);

Why is base a signed integer? Do we support negative bases?

We certainly ought to be checking that base is not 0 or 1 before converting. Don't trust user input!

 if ((int)temp-temp != 0) {

Although this is used as a test for having a fractional part, this may also be true for inputs outside the range of int. A safer test would be to use trunc() - note you'll still want to check the range before any conversion to integer type.

int digitCount(int input, int base){
    int rem;

What's rem for? We assign to it, but never use it, so it can just be removed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.