C code for converting decimal to any base (from 2 to 36)
Asked Answered
G

6

3

I have just recently started learning C. I wrote a very short program that converts between decimal and binary. I wanted to try and write a code that converts between decimal and any base (up until 36). However, my code just prints out garbage.

#include <stdio.h>
#include <string.h>

void printBase(int n, int k, int i, char a[])
{
    int placeholder;
    if (n != 0)
    {
        //return n % 2 + 10 * printBinary(n / 2);
        placeholder=(char)(n%k);
        if(placeholder>=10)
        {
            a[i] = (char)(placeholder - 10) + 'A';
        } else {
            a[i] = (char)placeholder;
        }
        i++;
        printBase(n/2, k, i, a);
    }
    for (i=0; a[i]!='\0'; i++)
    {
        printf("%c", a[i]);
    }
    return;
}

void reverse(char fromStr[], char toStr[])
{
    int i, j=0;
    i=getchar();
    for (i=0; fromStr[i]!='\0'; i++)
    {
        j++;
    }
    i=0;
    while (j>=0)
    {
        toStr[i]=fromStr[j];
        i++;
        j--;
    }
    printf("%s", toStr);
}

int main()
{
    int n, k;
    char a[81], b[81];
    setvbuf(stdout, NULL, _IONBF, 0);
    printf("Enter a deicmal number you want to convert to binary: ");
    scanf("%i", &n);
    fflush(stdout);
    printf("Enter a base: ");
    scanf("%i", &k);
    printBase(n, k, 0, a);
    //printf("%s", a);
    //reverse(a, b);
    return 0;
}

I thought the problem was with my reverse function but it works fine outside of this code. Even when I print out string a inside the printBase function it prints out garbage. What is the problem here?

Guardhouse answered 22/10, 2018 at 15:19 Comment(4)
One issue that I see: printBase(n/2, k, i, a); should be printBase(n/k, k, i, a);.Mohamedmohammad
You probably want a[i] = (char)placeholder + '0'; in else, but that doesn't fix your problem.Backbend
Your reverse function is indeed also incorrect. The null termination character ends up in toStr[0] instead of at the end. Try changing the while loop to i = 0; while (j > 0) { toStr[i] = fromStr[j - 1]; i++; j--; } toStr[i] = '\0';Chlordane
If you have an answer for your own post, post it below as an answer. Post rolled back.Bryology
N
1

Based on your code, the following does what you want. It places in a a reverse conversion that must still be printed backwards:

void convertBase(int n, int k, char a[])
{
    int j, i=0, sign= 0;
    if (n==0) a[i++]='0';
    if (n<0 ) {sign= -1; n= -n;}
    while (n>0) {
        j= n%k;
        if (j<10)
            a[i]= j+'0';
        else
            a[i]= j+'A';
        n= n/k;
        i++;
    }
    if (sign== -1) a[i++]= '-';
    a[i]= 0;
}

And here is revert:

void revStr(char *s)
{
    char c;
    int i=0, j=0;
    while (s[i]) i++; i--;
    while (i>j) {
        c= s[j];
        s[j]=s[i];
        s[i]= c;
        i--; j++;
    }
}
Nabataean answered 22/10, 2018 at 15:44 Comment(3)
@chux, both are special cases. I added themNabataean
convertBase(int n, int base, char a[]) need not be a special case if a do {} while (n>0); loop was used.Bryology
n= -n; is UB when n = INT_MIN. convertBase(INT_MIN=,... has trouble here.Bryology
D
1

With some general implementation of itoa

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

static const char* DIGISTS = "0123456789ABCDEFGHIKLMNOPQRSTVXYZ";

void itoa(long long i, unsigned char radix, char* to) {
    char *s = to + 65;
    char sign;
    unsigned len;
    if(i < 0) {
        sign = 1;
        len = 2;
    } else {
        sign = 0;
        len = 1;
    }
    *s = '\0';
    do {
        *(--s)= * ( DIGISTS + abs(i % radix) );
        i /= radix;
        ++len;
    } while(i != 0);
    if(sign)
        *(--s) = '-';
    memmove( to, s, len );
}

int main(int argc, const char** argv)
{
    char a[65];
    itoa( LLONG_MAX, 2, a);
    printf("binary: %s \n", a);
    itoa(12345, 10, a);
    printf("digit: %s \n", a);
    itoa(64018, 16, a);
    printf("hex : 0x%s \n", a);
    itoa(-24, 24, a);
    printf("base 24 : base24x%s \n", a);
    itoa(LLONG_MAX, 36, a);
    printf("base 36 : base36x%s \n", a);
    return 0;
}
Desirous answered 22/10, 2018 at 16:13 Comment(0)
J
0
#define c ('A' - 10)


int n = 4564567; // any number
int b = 16; // any base

int tmp = n < 0 ? -n : n;
int i = 0;

while (tmp)
{
    tmp /= b;
    ++i; // you need to calculate how long will be the number
}

while (i--)
{
    a[i] = n % b + ((n % b < 10) ? '0' : c); // you have to check if the remaining is below 10 or not. That is very important
    n /= b;
}

I think you forgot to add '0' in the else case

Adapted from an old source file https://github.com/agavrel/42-ft_printf/blob/master/srcs/pf_number.c

Judaist answered 22/10, 2018 at 15:35 Comment(0)
B
0

An alternative to reversing the array uses recursion.

As the number of digits in some integer type in never so great, recursion will not be excessive.

The below used a do {} while loop to avoid a special case with printBase(0).
It also uses negative values in printBase_helper() where /,% is well defined with C99. This avoids undefined behavior of code like n = -n when n == INT_MIN.

void printBase_helper(int neg, int base) {
  if (neg <= -base) {
    printBase_helper(neg / base, base);
    neg %= base;
  }
  putchar("0123456789ABCDEFGHIJKLMONOPQSTUVWXYZ"[-neg]);
}

void printBase(int n, int base) {
  if (n < 0) {
    putchar('-');
  } else {
    n = -n;
  }
  printBase_helper(n, base);
}

Test code

int main(void) {
  int value[] = {0, 1, -1, 10, INT_MAX, INT_MIN};
  int base[] = {10, 2, 36};
  for (unsigned v = 0; v < sizeof value / sizeof value[0]; v++) {
    for (unsigned b = 0; b < sizeof base / sizeof base[0]; b++) {
      printf("Base %2d, value %11d, --> base %2d, value ", 10, value[v], base[b]);
      printBase(value[v], base[b]);
      printf("\n");
    }
  }
  return 0;
}

Output

Base 10, value           0, --> base 10, value 0
Base 10, value           0, --> base  2, value 0
Base 10, value           0, --> base 36, value 0
Base 10, value           1, --> base 10, value 1
Base 10, value           1, --> base  2, value 1
Base 10, value           1, --> base 36, value 1
Base 10, value          -1, --> base 10, value -1
Base 10, value          -1, --> base  2, value -1
Base 10, value          -1, --> base 36, value -1
Base 10, value          10, --> base 10, value 10
Base 10, value          10, --> base  2, value 1010
Base 10, value          10, --> base 36, value A
Base 10, value  2147483647, --> base 10, value 2147483647
Base 10, value  2147483647, --> base  2, value 1111111111111111111111111111111
Base 10, value  2147483647, --> base 36, value ZIK0ZJ
Base 10, value -2147483648, --> base 10, value -2147483648
Base 10, value -2147483648, --> base  2, value -10000000000000000000000000000000
Base 10, value -2147483648, --> base 36, value -ZIK0ZK
Bryology answered 22/10, 2018 at 19:18 Comment(0)
G
0

I didn't know that answers to my own question should be posted below, sorry! But here is the code that I wrote on my own if it helps anyone:

#include <stdio.h>
#include <string.h>

void printBinary(int n, int k, int i, char a[])
{
    int placeholder;
    if (n != 0)
    {
        placeholder=(n%k);
        if(placeholder>=10)
        {
            a[i] = (placeholder - 10) + 'A';
        } else if(placeholder>=0 && placeholder<=9){
            a[i] = placeholder + '0';
        }
        i++;
        a[i]='\0';
        printBinary(n/k, k, i, a);
    }
    return;
}

int main()
{
    int n, k;
    char a[81], b[81];
    setvbuf(stdout, NULL, _IONBF, 0);
    printf("Enter a deicmal number you want to convert to binary: ");
    scanf("%i", &n);
    fflush(stdout);
    printf("Enter a base: ");
    scanf("%i", &k);
    printBinary(n, k, 0, a);
    n=strlen(a);
    k=0;
    n--;
    while (n>=0)
    {
        b[k]=a[n];
        n--;
        k++;
    }
    b[k]='\0';
    printf("%s", b);
    return 0;
}
Guardhouse answered 23/10, 2018 at 7:16 Comment(0)
C
0
    Try this one.

#include<stdio.h>
    int main()
    {
        int n,b,t1,i=0;
        float t2,t3,t4;
        int a[10];
        scanf("%d%d",&n,&b);
        for( i=0; n!=0; i++)
        {
            t1=n/b;
            t2=(float)n/b;
            t3=(float)t2-t1;
            t1=t3*b;
            t2=(float)t3*b;
            t4=(float)t2-t1;
            if(t4>=0.5)
            {
                a[i]=t3*b+1;

            }
            else
            {
                a[i]=t3*b;
            }
            n=n/b;
        }
        for(int j=i; j>0; j--)
        {
            printf("%d",a[j-1]);
        }

    return 0;
    }
Closestool answered 30/5, 2020 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.