如何用算法把一个十进制数转为十六进制数-C语言基础
如何⽤算法把⼀个⼗进制数转为⼗六进制数-C语⾔基础
这⼀篇⽂章要探讨的是“如何⽤算法实现⼗进制转⼗六进制”并不涉及什么特别的知识点。属于C语⾔基础篇。
在翻素材的时候,发现⼀篇以前写的挺有意思的代码,这篇代码⾥⾯涉及的知识点没有什么好讲的,也没有什么特别的逻辑概念在⾥⾯,仅仅只是想要分享⼀下个⼈对于编程⽅⾯的⼀些思考和坚持⽽已。
先看代码:
#include <stdio.h>
#include <string.h>
int Judge(int n);
int Detection(void);
int main(void)
{
char x[16] = {'0','1','2','3','4','5','6','7','8',
'9','a','b','c','d','e','f'};//⼗进制与⼗六进制对应的数组
printf("请输⼊⼀个⼗进制的数:");
int n = Detection();//输⼊数据检查再赋值
int k = Judge(n);//检测数组需要的长度
char y[k];//创建数组储存⼗六进制数
memset(y,'\0',sizeof(y));//清空数组
int i,j;
j = 0;
while( n >= 16 )//把转换好的⼗六进制数依次输⼊数组
{
今日出伏 你感受到了吗
i = (n % 16);//先是求余
y[j] = x[i];//把得到的余数转为⼗六进制数(例如“11”转“b”)
j++;//数组下标移位
n /= 16;//求商再赋值给它⾃⼰(⽅便下个循环再除)
if(n < 16)
y[j] = x[n];
}
//此时数组y内的⼗六进制数是倒过来储存的
printf("你输⼊的数转换成⼗六进制为:0x");//先输出“0x”前缀
while(j >= 0)//把储存了⼗六进制数的数组倒着输出
{
有什么好看的电影推荐一下if(j > 0)//判断是不是最后⼀个,是的话换⾏
printf("%c", y[j]);
else
printf("%c\n",y[j]);
j--;
感恩节对老师的感谢语}
return 0;
}
int Judge(int n)//这个函数的作⽤是⽤来判断需要定义的数组⼤⼩的
{
int k = 1;
int m = n;
while(m > 16)//如果⼩于16,那么1位就⾏了
{
m /= 16;//如果⼤于16先除与16
k++;//加⼀位
}
return k;
}
int Detection(void)//这个是第⼀篇博客⾥⾯的那个代码的封装版,⽤来保证输⼊的数为合法
{
int n;
while(1)
{
if(scanf("%d", &n) != 1 || getchar() != '\n')
{
printf("你输⼊的数据有误,请再输⼀遍:");
while(getchar() != '\n');
}else
break;
}
return n;
}
这篇代码所要实现的功能很简单,就是把⼗进制转换为⼗六进制输出,当然也是有前提的,就是不能⽤那些转换符(例如%x)或者⽤⼀些现有的函数,需要⾃⼰写⼀个算法来实现转换。⾄于这个算法也不难,⽆⾮就是了解⼀下在数学上⾯如何把⼗进制转为⼗六进制,然后把那个过程⽤代码来实现罢了,⽹上已经有很多说明了。⼗进制转其他进制最常⽤的办法就是不断对其要求的进制数求余,然后余数反转。
⼤概类似于这个样⼦的过程(灵魂画师附体)
这个过程在算法上⾯具体体现为先获取⽤户的⼗进制输⼊,然后不断的对其与16进⾏求商求余,把得到的余数反转输出,即为所要求的⼗六进制数。在这个过程中,由于需要把余数反转输出,没法每求⼀个余数就输出⼀个。所以就需要⼀个数组来存储这些已经求得的余数,然后再反向输出。在这整个输出的过程中,所涉及算法的难度并不⼤。但如果仅仅只是这样的话,我也没有必要专门写⼀篇⽂章来分享这个代码了。
我在写这个代码的时候,遇到⼀个问题,是关于数组的。既然我在输出之前需要把余数⽤数组储存起来,那么我这个数组需要定义多⼤呢?由于⽤户的输⼊并不确定,所以最终所得到的⼗六进制数也不确定,这样也就没有办法事先知道我需要的数组⼤⼩。定义⼤了浪费空间,定义⼩了⼜不够放。当初在做这道题的时候,⽼师给我们的建议是定义个“char x[20]”就可以了。
我当时的第⼀反应就是,⽼师这是在给我们降低难度啊,这么随便的吗?万⼀⽤户输⼊的数据转换为⼗六进制之后超过20位呢?
且不说浪费不浪费空间的问题,你这明显就是存在着bug啊!怎么也得要给个1024吧,20哪⾥够了。不过后来想想,如今的操作系统也就64位,转换成⼗六进制的话,也就16个数就可以表⽰完了,连20都给多了,四舍五⼊刚好取整嘛。⽽且也没有bug的存在,也就浪费了4个字节的内存⽽已。要是我当时意识到这点,我可能就会直接“char x[16]”完事。也就没有后⾯的什么事了。
不过在当时的我看了来,这简直就是⼀个要逼死强迫症的bug啊!我可以容许浪费空间,也可以容许效率低下,但是绝不能放任bug不管啊。所以,我那天苦思冥想,最终认识到,我需要的是⼀个可变数组。这个数组要能够实现我放多少东西进去它就能存多少东西,我拿多少东西出来它就能缩⼩多少。为了实现这个需求,我上⽹了⼀下可变数组的实现⽅法。但是不外乎两种情况,⼀种是在说C语⾔中没有可变数组,另⼀种就是在⽤代码实现可变数组。只可惜我当时的技术⽔平有限,实在是看不懂那些天书,⽽且那些⼤佬的代码⼀长,就不写注释的了,通篇博客就⼀整篇代码,⼀点介绍性的⽂字都没有,别说我当时没那个技术看不懂啊,我就是现在看的懂也没耐⼼看你这么⼀整篇没有注释的代码啊!简直神烦(这也是我想要写博客的⼀个原因)。
所以我当时在这模凌两可的⽹络环境下⾯,我认为是有可变数组的,只是藏着某个函数库⾥⾯⽽已,只是属于深度C⽽已,只是我还没有学到⽽已,于是那⼀整个下午我就都在探索可变数组。
直到后来我才知道,在C语⾔⾥⾯,本⾝就不存在什么可变数组,在C++中倒是存在可变数组的概念,⽹络上⾯的所谓可变数组,不过是利⽤了指针来存储好原数组的内存位置然后当再次需要改变数组⼤⼩的时候,在原位置上⾯创建或者把原数据拷贝到新的内存地址上⾯再返回新地址的值给原指针⽽已。说⽩了,就是假的,假的。根本就不存在什么可变数组。C语⾔本⾝就不⽀持可变数组这个功能。
直到的最后,当然是没有成功啦,本来就是不存在的东西,不过现在想想⽤储存原数组地址这个⽅法来实现可变数组⽤在我这篇代码中或许也很合适,虽然我⽤的⽅法是在数据输⼊之后先判断⼀下需要的数组⼤⼩,然后再创建数组的⽅法。不过那也是我当时的权宜之计⽽已,
有意思的是当初我在不知道C语⾔中有没有可变数组的时候,曾想过⽤“指针对于⾮法内存的访问”来实现可变数组。具体表现可以看下⾯的代码
int main(void)
{
int i = 0;
char a[i];//根本没有分配空间,⽤“i”代替0是为了防⽌编译器报警告
char *c = a;//⽤⼀个指针来存储数组“a”的地址值
int j = 3;
a[j] = '7';//这⾥⽤“j”来代替3是为了防⽌编译器报警告
printf("%c ", c[3]);//这⾥⽤“c”来代替“a”输出也是为了防⽌编译器报警告
printf("\n");
哀悼用语
return 0;
}
在这段代码⾥⾯数组“a”我根本没有分配空间给它,但是我却给它第3个位置“a[3]”赋值,居然编译通过了,运⾏也没有问题。这就是利⽤了指针对于⾮法内存的访问来实现的,⽽且这样也可以满⾜我的需求,我这个数组即没有⼤⼩限制的⽽且也丝毫不浪
费内存,这不就是我想要的可变数组吗?
但别以为这是什么好东西,恰恰相反在编程开发的时候,我们应该要去杜绝这种情况的发⽣。这段代
码在不同的电脑下⾯或者在不同的程序区域下⾯运⾏都有可能不⼀样,你可以尝试把它封装成⼀个独⽴函数,然后试着在另外⼀篇⼩规模的代码上⾯调⽤试试看,可能在程序的开始调⽤它,程序就会报段错误,也有可能会在程序的尾部调⽤它,程序就报段错误了。也有可能整个程序执⾏完到退出,也没有报段错误。什么时候报段错误,完全取决于CPU在执⾏你这个程序的过程中什么时候访问到你正在使⽤的那块⾮法内存。
你的代码⼀运⾏就报错不可怕,最可怕的就是这种随机性报错的,你⽆法准确定位到你的错误位置。想象⼀下,你代码原本运⾏的好好的,你突然想给它来个优化,就好像把原本的int形数据改为char形的节省⼀下空间,或者改⼀下别的⽆关痛痒的细节,改完之后吧,你⼀编译运⾏,报错了,你就啊啊啊,就是不到在哪⾥有错误。
然后你就很不⽢⼼的把代码⼜改回去,但是你忽略了⼀个细节,你原本是先定义⼀个char类型的数据“a”然后再定义⼀个int类型的数据“b”的,但是你为了好看,你在优化的时候把它们改成了先定义“b”再定义“a”了。但是你在改回去的过程中觉得不可能是这⾥的问题啊,就没管了,结果编译运⾏后,还是报错。
这时候你对着整篇代码从头看到尾,⼜从尾看到头,你看了好⼏遍,但就是不知道到底是哪⾥出了问题,明明跟原来的代码⼀摸⼀样啊,怎么就还是报错呢?这时候打死你也不会相信,就是因为你改变
了那两个变量的定义顺序了,使得整个程序在内存中的储存结构发⽣了改变,这就造成了程序在运⾏的过程中访问到了原本不会访问的内存,⽽那块内存正是你⽤的⾮法内存。
所以当时我在把这个思路运⽤到代码⾥⾯的时候,就出现了很多奇奇怪怪的问题,程序有时候⾏,有时候不⾏。有的时候甚⾄会出现同⼀个代码在我的电脑上⾯运⾏还可以⼀放到别⼈的电脑上⾯就有不⾏了这种情况,更夸张的是有时候上午运⾏可以,下午运⾏⼜报错了。搞了半天,放弃了。直到后来知道了野指针的概念之后,才渐渐知道为什么会出现那种情况。对于野指针的分析,以后有机会我可能还会单独写⼀篇⽂章来说明吧,也可能不会。虽然野指针还是挺重要的⼀个概念的,不过也挺简单,好像也没什么好写的。
好了,就写到这⾥吧,确实没有什么知识点好说的,只是单纯的想要分享⼀下以前的⼀些有趣的事情⽽已。⽽且如果你刚好需要做⼀道编程题叫做”请⽤算法编程实现⼗进制数转XX进制数“的时候,这篇代码刚好可以套⽤嘛!不过不建议抄作业啦!参考参考就可以了,毕竟真没有什么难度的这题,注释代码⾥⾯都写明⽩了,应该也不会存在看不懂的现象,过些天我会尝试性的把这个例⼦改为⽤“储存原数组地址来实现可变数组”的⽅法来实现,然后再更新上来。
最后附上这个例⼦的精简版代码:
#include <stdio.h>
#include <string.h>
int Judge(int n);
int Detection(void);
int main(void)
{
char x[16] = {'0','1','2','3','4','5','6','7','8',
'9','a','b','c','d','e','f'};//⼗进制与⼗六进制对应的数组
printf("请输⼊⼀个⼗进制的数:");
int n = Detection();//输⼊数据检查再赋值
int k = Judge(n);//检测数组需要的长度
char y[k];//创建数组储存⼗六进制数
memset(y,'\0',sizeof(y));//清空数组
倒车影像摄像头int i,j;
for(j=0; n > 0; j++)//把转换好的⼗六进制数依次输⼊数组革的拼音
{
i = (n % 16);
y[j] = x[i];
n /= 16;
}
printf("你输⼊的数转换成⼗六进制为:0x");
while(j >= 0)//把储存了⼗六进制数的数组倒着输出
printf("%c", y[--j]);
printf("\n");
return 0;
}
int Judge(int n)//这个函数的作⽤是⽤来判断需要定义的数组⼤⼩的
{
int k;
for(k=0; n>0; ++k)
n /= 16;
return k;
}
int Detection(void)//这个是第⼀篇博客⾥⾯的那个代码的封装版,⽤来保证输⼊的数为合法
{
int n;
while(1)
{
if(scanf("%d", &n) != 1 || getchar() != '\n')
{
printf("你输⼊的数据有误,请再输⼀遍:");
while(getchar() != '\n');
}else
break;
}
return n;
}
原博客始发于CSDN,在如今博客界的转载抄袭泛滥的环境下,原创不易,点个赞再⾛呗。以下是博客⾸页的链接。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。