2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 面试题--位操作--将十进制数转换为16进制字符串输出

面试题--位操作--将十进制数转换为16进制字符串输出

时间:2023-07-06 20:51:52

相关推荐

面试题--位操作--将十进制数转换为16进制字符串输出

这是一道面试题:

编程实现将十进制数转换为16进制输出,不得使用任何已定义的库函数,比如string,math等。

char * get16String(long num){int i = 0;char * buffer = (char *)malloc(11);char * temp = buffer+2;buffer[0] = '0';buffer[1] = 'x';buffer[10] = '\0';for(i=0;i<8;i++){temp[i] = (char)(num << 4 * i >> 28);/*乘法优先级高于移位符, 移位符左结合,然后再右结合*/temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16; /*之所以会出现负数是因为:左移之后,若最高位为1,则编译器认为该数为负数,执行右移操作(该编译器执行算术移位)时,移入位均用1补齐*/temp[i] = temp[i] < 10 ? temp[i] + '0' : temp[i] - 10 + 'A' ;// temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55; //等同于上一句0的ASCII码的十进制值是48,A是65}/*从高位开始,每一次循环都取出num的二进制码中的四位,并转换成一个16进制的数值。*/return buffer;}

实际上你这题目的算法用到位运算 整数是32个bit

16进制实际上 是4个bit 4个比特一组 一共8组

每次把4个bit取出来做成一个整数 输出就行了

temp[i] = (char)(num<<4*i>>28);

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

回答

temp[i] = (char)(num<<4*i>>28); 左移4i位 去掉高位的4i 右移28位 去掉右边的 这就获得4个bit

第一次是最高位32-29 4个bit 第二次 28-25 4个bit

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

然后因为它可能是个有符号的数 所以加上16 吧这个数变成0~15之间的正数

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

然后<10 就是变成字符‘0’~‘9’所以加上48,如果>=10那就要用'A'~'F'来表示

所以加上55, 因为'A'变成整数正好是65

同理,可应用于二进制的转换

1:循环对数字1左移31-i(i={0,31})位(从高位开始的),再与把num作位与操作,

2:再把刚才的结果通过右移31-i (i={0,31}) 位得出每一位是否为0还是1,

这样就得到了每一位的二进制位,再把这些二进制位拼成字符串就OK了!

char * get2String(long num){int i = 0;char * buffer = NULL;char * temp = NULL;buffer = (char *)malloc(33);temp = buffer;for(i=0; i<32; i++) {temp[i] = num & (1 << (31 - i));temp[i] = temp[i] >> (31 - i);temp[i] = (temp[i] == 0) ? '0' : '1';}buffer[32] = '\0';return buffer;}

上面这个是别人写的,其实这个是错的,因为它没有考虑负数的情况,负数移位,符合位是被补上的。比如1000 0000 0000 0000 0000 0000 0000 0000>>31 =1000 0000 0000 0000 0000 0000 0000 0001=-2147483647而不是等于1.所以必需清除符号位。对于指定位的置1和清0操作可以用下面的宏定义,比较直观简单。

#define setbit(x,y) x|=(1<<y) //将X的第Y位置1

#define clrbit(x,y) x&=~(1<<y) //将X的第Y位清0

修改后的函数如下:

char * get2String(long num){int i = 0;char * buffer = NULL;char * temp = NULL;long t;buffer = (char *)malloc(33);temp = buffer;for(i=0; i<32; i++)//(+3)在32位系统中的存储为二进制 0000 0000 0000 0000 0000 0000 0000 0011 { //(-3)在32位系统中的存储为二进制1111 1111 1111 1111 1111 1111 1111 1101t = num & (1 << (31 - i));//1111 1111 1111 1111 1111 1111 1111 1101 & 1000 0000 0000 0000 0000 0000 0000 0000=1000 0000 0000 0000 0000 0000 0000 0000=-2147483648 t= t >> (31 - i);//1000 0000 0000 0000 0000 0000 0000 0000>>31 =1000 0000 0000 0000 0000 0000 0000 0001=-2147483647 clrbit(t,31);//将最高位清零temp[i] = (t == 0) ? '0' : '1';}buffer[32] = '\0';return buffer;}

3.通常的,十六进制和二进制的输出都将前面的0去掉,添加去掉0的代码如下:

char * get2String(long num){int i = 0,j=0;char * buffer = NULL;long t;buffer = (char *)malloc(33);for(i=0; i<32; i++) { t = num & (1 << (31 - i)); t= t >> (31 - i);clrbit(t,31);//将最高位清零buffer[i] = (t == 0) ? '0' : '1';}for(i=0; i<32; i++) //去掉前面的0if(buffer[i] !='0')break;for(j=0; j<32-i; j++) //非0值开始往前移buffer[j]=buffer[i+j];buffer[j] = '\0';return buffer;}char * get16String(long num){int i = 0,j=0;char * buffer = (char *)malloc(11);char * temp = buffer+2;buffer[0] = '0';buffer[1] = 'x';for(i=0; i<8; i++){//temp[i] = (char)( (num << (4 * i)) >> 28);temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;} for(i=0; i<8; i++) //去掉前面的0if(temp[i]!='0')break;for(j=0; j<8-i; j++) //非0值开始往前移buffer[2+j]=temp[i+j];buffer[2+j] = '\0';return buffer;}

4.其实用取模再求余的方法也可以实现,只是需要将得到的余数序列倒序,才行。而且对于负数不行,负数的话该怎么办呢?

char* exchange2(int n) //适用于正数//void exchange2(int n){ int j,temp; char *d; d = (char *)malloc(sizeof(char)*2); for (j = 0;; j++) { temp = n % 2; d[j] =temp + '0'; n /= 2; if (n == 0) break; else d = (char *)realloc(d, strlen(d)+1);///这样改 } j++; d[j] = '\0'; //倒序 int i=0; char a; while(i<j-1) { a=d[i]; d[i]=d[j-1]; d[j-1]=a; ++i; --j; } //free(d);return d;}char* exchange16(int n) //适用于正数{ int j,temp; char * buffer = (char *)malloc(11);//char buffer[12]={'\0'}; /*这里不能用这个,因为这相当于定义了一个局部变量---数组buffer[],而返回的是一个指针,是这个内存块的首地址,然后这个这个局部变量的生存期到了,也就是内存被回收了,然后这个buffer指针指向哪里呢?所以运行的时候程序就会崩溃。*/buffer[0] = '0';buffer[1] = 'x';j=2;while(n){temp = n % 16; if(temp>=0&&temp<=9)buffer[j] =temp + '0'; //0~9字符 else buffer[j] =temp -10+ 'A'; //A~F字符n /= 16; j++;} //倒序 int i=2; char a; while(i<j-1) { a=buffer[i]; buffer[i]=buffer[j-1]; buffer[j-1]=a; ++i; --j; } buffer[i+1] = '\0'; //free(buffer); //这个应该怎么在哪里free()呢?return buffer;}

同时,从以上两个程序中学习了

malloc和

realloc的使用,以及他们与数组定义的却别。在下一节讨论总结。

1、realloc函数用法。

指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)

malloc动态分配与数组静态分配还有一个最重要的区别:

1.全局

假设数组char a[10]和char*p=(char*)malloc(10)都是全局的

那么数组a[10]在程序运行过程会一直存在,即一直占用10个字节空间.

但动态申请的可以使用free()来释放掉.等到再使用的时候重新申请.

2.局部

局部的数组在超过其作用域范围内会释放掉,但动态申请出来的空间不会.

如.

char *fun()

{

char p[10];//局部的数组

return p;//返回一个临时的局部变量,这个函数一结束,p的空间就会释放掉,所以是没有返回成功的.

}

char *fun()

{

char *p=(char*)malloc(10);//动态申请空间

return p;//返回动态申请的空间是可以的.

}

void main()

{

char *s=fun();//

strcpy(s,"abc");//如果fun()里是动态申请的,可以拷贝成功,否则不成功,是乱码.

}

5.由此,回头看看前面的malloc函数,使用时没有配对使用free函数,这是很不科学的,也是不应该的。

char * get2String(long num)

{

int i = 0,j=0;

char * buffer = NULL;

long t;

buffer = (char *)malloc(33);

for(i=0; i<32; i++)

{

t = num & (1 << (31 - i));

t= t >> (31 - i);

clrbit(t,31);//将最高位清零

buffer[i] = (t == 0) ? '0' : '1';

}

for(i=0; i<32; i++) //去掉前面的0

if(buffer[i] !='0')

break;

for(j=0; j<32-i; j++) //非0值开始往前移

buffer[j]=buffer[i+j];

buffer[j] = '\0';

return buffer;

}

char * get16String(long num)

{

int i = 0,j=0;

char * buffer = (char *)malloc(11);

char * temp = buffer+2;

buffer[0] = '0';

buffer[1] = 'x';

for(i=0; i<8; i++)

{//

temp[i] = (char)( (num << (4 * i)) >> 28);

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

}

for(i=0; i<8; i++) //去掉前面的0

if(temp[i]!='0')

break;

for(j=0; j<8-i; j++) //非0值开始往前移

buffer[2+j]=temp[i+j];

buffer[2+j] = '\0';

return buffer;

}

void main()

{

int n;

char str[80];

scanf("%d",&n);

str=get16String(n);

printf("%s\n",str);

str=get2String(n);

printf("%s\n",p);

}

这样是编译不过的,编译有错

str=get16String(n);

rror C2440: '=' : cannot convert from 'char *' to 'char [80]

修改成这样才行的

void main()

{

int n;

char str[80];

char*p=str;

scanf("%d",&n);

p=get16String(n);

printf("%s\n",p);

p=get2String(n);

printf("%s\n",p);

}

这样是能正确输出程序但是程序还是有问题的,用了malloc函数但是没用free释放掉内存,这是很不科学的,面试时这样写的话,你就pass了,尤其是面试嵌入式工程师的,应该这样修改

修改版本一:

void get2String(long num)

{

int i = 0,j=0;

char * buffer = NULL;

long t;

buffer = (char *)malloc(33);

for(i=0; i<32; i++)

{

t = num & (1 << (31 - i));

t= t >> (31 - i);

clrbit(t,31);//将最高位清零

buffer[i] = (t == 0) ? '0' : '1';

}

for(i=0; i<32; i++) //去掉前面的0

if(buffer[i] !='0')

break;

for(j=0; j<32-i; j++) //非0值开始往前移

buffer[j]=buffer[i+j];

buffer[j] = '\0';

printf("%s\n",buffer);

free(buffer);

}

在函数内使用printf();直接打印是不太好也不太方便后面的使用。

修改版本二:

void get2String(long num,char *buffer)

{

int i = 0,j=0;

long t;

for(i=0; i<32; i++)

{

t = num & (1 << (31 - i));

t= t >> (31 - i);

clrbit(t,31);//将最高位清零

buffer[i] = (t == 0) ? '0' : '1';

}

for(i=0; i<32; i++) //去掉前面的0

if(buffer[i] !='0')

break;

for(j=0; j<32-i; j++) //非0值开始往前移

buffer[j]=buffer[i+j];

buffer[j] = '\0';

}

void get16String(long num,char* buffer)

{

int i = 0,j=0;

char * temp = buffer+2;

buffer[0] = '0';

buffer[1] = 'x';

for(i=0; i<8; i++)

{//

temp[i] = (char)( (num << (4 * i)) >> 28);

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

}

for(i=0; i<8; i++) //去掉前面的0

if(temp[i]!='0')

break;

for(j=0; j<8-i; j++) //非0值开始往前移

buffer[2+j]=temp[i+j];

buffer[2+j] = '\0';

}

void main()

{

int n;

char str[80];

char*p=str;

scanf("%d",&n);

get16String(n,p);// get16String(n,str);//都可以

printf("%s\n",p);

get2String(n,str);

printf("%s\n",p);

}

修改版本三:

char* get2String(long num,char *buffer)

{

int i = 0,j=0;

long t;

char* tmp=buffer;

for(i=0; i<32; i++)

{

t = num & (1 << (31 - i));

t= t >> (31 - i);

clrbit(t,31);//将最高位清零

buffer[i] = (t == 0) ? '0' : '1';

}

for(i=0; i<32; i++) //去掉前面的0

if(buffer[i] !='0')

break;

for(j=0; j<32-i; j++) //非0值开始往前移

buffer[j]=buffer[i+j];

buffer[j] = '\0';

return tmp;

}

char* get16String(long num,char* buffer)

{

int i = 0,j=0;

char* retmp=buffer;

char * temp = buffer+2;

buffer[0] = '0';

buffer[1] = 'x';

for(i=0; i<8; i++)

{//

temp[i] = (char)( (num << (4 * i)) >> 28);

temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;

temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;

}

for(i=0; i<8; i++) //去掉前面的0

if(temp[i]!='0')

break;

for(j=0; j<8-i; j++) //非0值开始往前移

buffer[2+j]=temp[i+j];

buffer[2+j] = '\0';

return retmp;

}

void main()

{

int n;

char str[80];

char*p=str;

scanf("%d",&n);

p=get16String(n,p);// get16String(n,str);

printf("%s\n",p);

p=get2String(n,str);

printf("%s\n",p);

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。