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

蓝咒 提交于 2020-06-27 15:34:10

问题


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?


回答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++;
    }
}



回答2:


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;
}



回答3:


#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




回答4:


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



回答5:


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;
}



回答6:


    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;
    }


来源:https://stackoverflow.com/questions/52932715/c-code-for-converting-decimal-to-any-base-from-2-to-36

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!