要解决的问题是: 将任意(假定为m)进制的一个数字转化为n进制的数据。 基本思路是m进制转化为2进制,再二进制转化为n进制。 相比于许多同仁的代码,解决的范围大了一些(比如数值可以超过long什么的)

  • 使用了 C++ 的引用和 bool 类型. 需要纯 C 实现改了这儿就好
  • 暂且使用 g++ xxx.cc -Wall 编译 0 error , 0 warning.
#include <stdio.h>
#include <string.h>

#define DATALENGTH 1000

/**
 * m 进制数转化为 2进制数 输入说明:
 * char * mm : 格式化好的m进制数(格式化方法见stoc)
 * int m : m 进制
 * int ilen : 输入字符串长度
 * bool * bb : 输出的二进制数组(需要预留足够长的空间)&&(从低位到高位排列)
 * int &olen : 输出字符串长度
 *
 */
bool mtob(char *mm,int m,int ilen,bool *bb,int &olen) // mm -> bin
{
    int mlen = 0;
    int slen = 0;
    int elen = ilen;
    bool tt;
    int now;
    bb[mlen] = mm[elen-1] % 2;
    mlen ++;
    while(slen <= elen)
    {
        tt = 0;
        for(int i = slen ; i < elen ; i ++)
        {
            now = (mm[i] + tt * m )/ 2;
            tt = ((mm[i] + tt * m )%2 == 1)? 1 : 0;
            mm[i] = now ;
        }
        bb[mlen] = mm[elen-1] % 2;
        mlen ++;
        while(mm[slen] == 0 ) slen ++;
    }
    olen = mlen-1;
    return true;
}

// format string
int fmtstr(char str[],int n,int len)
{
    int tt = 0;
    int i;
    int now ;
    for(i = 0 ; i < len || tt ; i ++ )
    {
        if(str[i]+tt >= n)
        {
            now = (str[i] + tt) % n;
            tt = (str[i] + tt) / n;
            str[i] = now ;
        }else
        {
            str[i] = str[i] + tt;
            tt = 0;
        }
    }
    return i > len ? i : len;
}


// 值得一提的是,我没有传递str的len,原因有2:
// 1. 由于是从低位到高位,所以str的长度必然<=tmp的长度
// 2. str已经被撸顺了,所以只撸tmp和tmp+str中需要撸的那一段即可
//   比如:(从高位到低位)
//        123456
//     +      99
// ---------------
//           555
// 虽然返回长度为3,但实际上已经被处理完毕了: 123456+99 = 123555
// 但是,在调用的时候,就要比较一下,真实长度是3还是6了
// 如果要在其他地方也参考这个函数,请务必了解这点
int addit2(char str[],int n,int level)
{
    char tmp[DATALENGTH];
    int len = 1;
    tmp[0] = 1;
    for(int i = 1 ; i < DATALENGTH ; i++) tmp[i] = 0;
    // generate a 2^level string
    for(int i = 0 ; i < level ; i ++)
    {
        for(int j = 0 ; j < len ; j ++) tmp[j] *= 2;
        len = fmtstr(tmp,n,len);
    }
    // add tmp -> str
    for(int i = 0 ; i < len ; i++) str[i] += tmp[i];
    return fmtstr(str,n,len);
}


// 二进制到N进制
bool bton(bool *bb,int n,int ilen,char *nn,int &olen) // bin -> nn
{
    for(int i =0;i<ilen;i++)
        if(bb[i]) olen = addit2(nn,n,i);
    return true;
}

bool stoc(char str[],int m,int len) // show -> count
{
    for(int i=0;i<len;i++)
    {
        if (str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 10;
        if (str[i] >= 'A' && str[i] <= 'Z') str[i] -= 'A' - 10;
        if (str[i] >= '0' && str[i] <= '9') str[i] -= '0';
        if(str[i] >= m) return false;
    }
    return true;
}

char * ctos(char str[],int len) // count -> show
{
    static char buffer[DATALENGTH];
    int j = 0 ;
    char ch[]="0123456789ABCDEFGHIJKLMNOPQRST";
    for(int i = len -1 ; i >= 0; i--) buffer[j++] = ch[(int)str[i]];
    return buffer;
}

/**
 * usage :
 *  ./a.out
 *  ./a.out nn
 *  ./a.out mm nn
 */
int main(int argc, char *argv[])
{
    int m,n;
    char mm[DATALENGTH];
    bool bb[DATALENGTH];
    char nn[DATALENGTH];
    char *np;
    int bblen;
    int mmlen;
    int nnlen;
    switch(argc)
    {
        case 1:
            m = 10;
            n = 2;
            break;
        case 2:
            m = 10;
            n = 0;
            for(unsigned int i=0;i<strlen(argv[1]);i++) n = n * 10 + argv[1][i]-'0';
            break;
        case 3:
            m = 0;
            n = 0;
            for(unsigned int i=0;i<strlen(argv[1]);i++) m = m * 10 + argv[1][i]-'0';
            for(unsigned int i=0;i<strlen(argv[2]);i++) n = n * 10 + argv[2][i]-'0';
            break;
        default :
            return 0;
    }
    if(m>16 || n > 16)
    {
        printf("ERROR: both m & n should less than 16\n");
        return -1;
    }
    printf("SET : %d -> %d\n",m,n);
    printf("input a number : ");
    scanf("%s",mm);
    mmlen = strlen(mm);
    printf("your input: %s (%d)\n",mm,mmlen);
    if(!stoc(mm,m,mmlen))
    {
        printf("Error input : Input Number Is Out Of Range!\n");
        return -1;
    }
    //printf("m -> b ...");
    mtob(mm,m,mmlen,bb,bblen);
    //printf("[ok]\n");
    //printf("b -> n ...");
    for(int i=0;i<DATALENGTH;i++) nn[i] = 0;
    bton(bb,n,bblen,nn,nnlen);
    np = ctos(nn,nnlen);
    //printf("[ok]\n");
    printf("result is : %s\n",np);
    return 0;
}
Categories: Code

Yu

Ideals are like the stars: we never reach them, but like the mariners of the sea, we chart our course by them.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *