目录
大致思路
设计一个函数,接收的四个参数为 输入值、输入值的进制、输出值、输出值的进制。
为实现进制转换的功能,可以先把输入值转化为十进制数,然后再转化为目标进制数,因为输入值和输出值都是用字符串进行存储的,所以最后要考虑输出值的第一个数是否位于字符串的首元素地址以及字符串末尾的\0。
1 输入值转化为十进制数
先将v初始化为0,最开始p指向第一个元素,第一个循环结束后v=2,之后的循环就是执行上图中(2*8+3)*8+5
如果输入值是十进制以上呢?那就要处理掉9以上的数:a~z,把这些字母换算成数字
若*p = b,它的ASCII码为98,而b代表11,所以*p应该等于 'b' - ( 'a' - 10 )
即v = v * s_in + (*p - ( 'a' - 10) )
写成三目操作符
v = v * s_in + (*p - ((*p >= 'a') ? ('a' - 10) : '0'));
当p指向\0时,循环结束
输入值转化为十进制数的代码如下
int v = 0;
for (char* p = in; *p; p++)
v = v * s_in + (*p - ((*p >= 'a') ? ('a' - 10) : '0'));
2 将十进制数转化为目标进制数
out[n--] = v % s_out;
n从out的最后一个元素的下标开始,每次赋值后 n - 1
如果商为0并且n自减到了首元素下标0,则循环结束。
同理,如果输入值是十进制以上,用三目操作符进行处理
这一部分的代码如下
int n;
for (n = 31; v && n; v = v / s_out)
out[n--] = (((v % s_out) < 10) ? '0' : ('a' - 10)) + (v % s_out);
3 最后调整
因为第二部分是从后往前赋值的,而且也没有加上\0,所以要用memmove把后面的值移到最前面,然后在最后面添上一个\0
代码如下
void NumberSystem(char* in, int s_in, char* out, int s_out)
{
int v = 0, n;
for (char* p = in; *p; p++)
v = v * s_in + (*p - ((*p >= 'a') ? ('a' - 10) : '0'));
for (n = 31; v && n; v = v / s_out)
out[n--] = (((v % s_out) < 10) ? '0' : ('a' - 10)) + (v % s_out);
memmove(out, out + n + 1, 32 - n - 1);
out[32 - n - 1] = 0;
}
测试代码
int main()
{
char out[33];
for (int s = 2; s < 36; s++)
{
NumberSystem("f4240", 16, out, s);
printf("16:f4240 => %2d:%s\n", s, out);
}
for (int s = 2; s < 36; s++)
{
NumberSystem("1000000", 10, out, s);
printf("10:1000000 => %2d:%s\n", s, out);
}
return 0;
}
以上测试代码 1.把16进制数f4240转换成2进制至36进制
2.把10进制数1000000转换成2进制至36进制
测试结果
代码来源:https://www.zhihu.com/question/430885980/answer/1640970548