前言:内容包括:题目,代码实现,大致思路,代码解读
题目:
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。
注意:
十六进制中所有字母(a-f)都必须是小写。
十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。
给定的数确保在32位有符号整数范围内。
不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。
示例 1:
输入:
26
输出:
"1a"
示例 2:
输入:
-1
输出:
"ffffffff"
代码实现:
char * toHex(int num)
{
char arr[] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
char* ret = malloc(9* sizeof(char));
ret[8] = '\0';
int index = 7;
int count = 8;
do
{
ret[index--] = arr[num & 0xf];
count -= 1;
num >>= 4;
} while (num && count);
return ret + index + 1;
}
大致思路:
将num的32个比特位每4位一转换(四个比特位=一个十六进制的数字):
1 一个arr数组存储16进制的所有数值:0~9 a~f
由于题目返回的是字符串类型,所以arr数组的每个元素都是字符,即'0'~'9' 'a'~'f'
2 num&0xf即可得到最低的四个比特位,0xf表示16进制的f
&:有0则0,双1则1
比如num是26(这里只显示从后往前的后8个比特位)
26的二进制位:0001 1010
0xf的二进制位: 0000 1111
26&0xf: 0000 1010 ->26的最后四个比特位
3 num的每四个比特位转换完成后,需要右移4位,效果是去掉这四个已经转换完成的比特位
但是:右移分为算术右移,和逻辑右移
leetcode上是算术右移,即正数右移时,右边抛弃,左边补0
负数右移时,右边抛弃,左边补1
4 什么时候是num的全部比特位转换完毕?
num为正数:当num为0时转换完毕(因为num转换完一组四个比特位,就会右移4个比特位,右移的同时左边会补0,当正数的num转换完毕后,它的32个比特位全是0)
num为负数:设置count来统计num的转换次数,当count由初始的8变成0时,代表转换完毕
(因为负数的num每转换完一组四个比特位,也需要右移这4个比特位,右移的同时左边会补1,所以负数的num转换完毕的判断条件不能用num是否变成0,我们知道32为比特位,四个为一组,可以分为8组,那么count初始值设置为8,表示现在有8组待转换,每转换完一组,count--,当8组全部转换完成后,count==0)
代码解读:
part 1
char* ret = malloc(9* sizeof(char));
ret[8] = '\0';//手动在最后一个空间加上字符串的结束标志'\0'
int index = 7;//正式存放转换好的元素的起始空间
int count = 8;//当num为负数时,根据count的变化判断其是否转换完成
1 malloc动态开辟一块空间,用于存放由数字num转成十六进制的字符串形式
32个比特位,每四个为一组,可以分为8组(四个比特位对应一个十六进制数)
故而一个num最多可以转成8个字符(一个字符是一个十六进制数字的字符形式)
再加上字符串末尾的'\0',共需8+1=9的空间
2 转换是从32个比特位的末尾开始转换的,所以我们需要倒着存放
part 2
do
{
ret[index--] = arr[num & 0xf];//对num后四个比特位进行十六进制的转换
count -= 1;//一组转换完成
num >>= 4;//去掉已经转换完成的一组四个比特位
} while (num && count);
return ret + index + 1;//返回第一个元素的地址
1 需要使用do-while循环,而不使用while循环,原因在于:
while的结束条件是:num&&count,前一个用于判断num为正数时,转换是否结束
后一个用于判断num为负数时,转换是否结束
num为真:正数的num还未转换完成
count为真:负数的num还未转换完成
但是当num为0时,若只是使用while循环,则num不会进入循环,也就不会对为0的num进行十六进制的转换
所以使用do-while循环,直接执行一次转换,这样当num为0时,也能发生十六进制的转换
2 ret + index + 1
num最多能转换成8个六进制的字符
这意味着,num存在这样情况:全部转换完成后,没有将空间填满
比如当num为26时,转换成:1a,只占了两个空间
由于我们是倒着存放的(因为转换是从32个比特位的后四位向前转换的),且index--是后置--
所以当转换完成后,index+1,就是第一个元素的下标,ret+index+1,就是第一个元素的地址