用于将小数转换为任何基数(从2到36)的C代码

时间:2018-10-22 15:19:15

标签: c base-conversion

我刚刚开始学习C。我编写了一个非常简短的程序,可以在十进制和二进制之间进行转换。我想尝试编写一个在十进制和任何基数(直到36)之间转换的代码。但是,我的代码只是打印出垃圾。

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

我以为问题出在我的反向函数上,但是在这段代码之外仍然可以正常工作。即使我在printBase函数内部打印出一个字符串,它也会打印出垃圾。这是什么问题?

6 个答案:

答案 0 :(得分:1)

根据您的代码,以下操作将满足您的要求。它在a中放置了一个 reverse 转换,该转换必须仍然向后打印:

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

这是还原:

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

答案 1 :(得分:1)

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

答案 2 :(得分: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;
}

我认为您在其他情况下忘记添加'0'

改编自旧的源文件https://github.com/agavrel/42-ft_printf/blob/master/srcs/pf_number.c

答案 3 :(得分:0)

对数组求逆的另一种方法是使用递归。

由于某种整数类型的位数从来没有那么大,因此递归不会过多。

下面使用do {} while循环来避免printBase(0)的特殊情况。
它还在printBase_helper()中使用负值,其中/,%在C99中定义良好。这样可以避免n = -nn == 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);
}

测试代码

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

输出

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

答案 4 :(得分:0)

我不知道自己的问题的答案应该在下面发布,对不起! 但是以下是我自己编写的代码,如果有帮助,它可以帮助您:

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

答案 5 :(得分: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;
    }