一个求十六进制的程序错误//带注释,帮我看看

发布网友 发布时间:2022-04-21 18:54

我来回答

3个回答

热心网友 时间:2023-12-07 14:46

1.字符是ASCII编码,数字0~9的编码是0x30~0x39,所以,将数字0~9加上0的ASCII编码0x30就是0x30~0x39了,就转换成了与它们对应的字符。程序中加'0',这是字符写法,就是0x30。C/C++允许这样写并与整形数运算。
2.你的代码对正数的处理是正确的,但对负数的处理有比较大的问题:对十进制数先变成了十六进制字符,而后才对“字符”求反加1求补码,这是错误的,求补只能对数据进行;而且加1会有进位发生的,但你只加在了最低位,所以错的地方比较多。改了一下,原来语句也留着,只是挂起来了,这样以便你对照。如下:
int main(void){/*主程序*/
int data,i=0,k,dx=1;
char a[16] = {0};
printf("输入一个十进制数");
scanf("%d",&data);
printf("OX");
if(data<0)//计算负数的十六进制
{
do
{
//switch((abs(data))%16)//每次循环会得到一个十六进制上的一个数
//{
// case 10:a[i] = 'A';break;//
// case 11:a[i] = 'B';break;//
// case 12:a[i] = 'C';break;//
// case 13:a[i] = 'D';break;//
// case 14:a[i] = 'E';break;//
// case 15:a[i] = 'F';break;//
// default:a[i] = data%16+'0';//为何一个整数+'0',等于字符?
//}
a[i]=(abs(data))%16;
data=(abs(data))/16;
i++;
}while(data);
k=i;
//i-=i;//求出a[0]
for(i--;i>=0;i--) a[i]=~a[i]&0xF;
for(i++;i<k;i++){
if(a[i]==15){//解决加1时的进位问题并变为字符
a[i]+=dx;
a[i]='0';
dx=1;
}
else{//无进位时的加1与转换为字符
a[i]+=dx;
if(a[i]>=0 && a[i]<10) a[i]+='0';
else a[i]+=0x37;//printf(":%c ",a[i]);
dx=0;
}
}
//while(!i)//数组下标最低位存着此数最低位的十六进制数,对最低位按位取反+1
//{
// a[i] = ~a[i]+1;
// printf("%c",a[i]);
// break;//计算一次跳出
//}
//while(k) //对数组下标i最后存着的数按位取反
//{
// printf("%c",~a[k]);
// break;
//}

while(k!=0) printf("%c",a[--k]);//这里改成前--因为多了
printf("\n");
return 0;
}
if(data>=0)
{
do
{
switch(data%16)
{
case 10:a[i] = 'A';break;
case 11:a[i] = 'B';break;
case 12:a[i] = 'C';break;
case 13:a[i] = 'D';break;
case 14:a[i] = 'E';break;
case 15:a[i] = 'F';break;
default:a[i] = data%16+'0';
}
data/=16;
i++;
}while(data);
while(i>-1)
printf("%c",a[--i]);//这里改成前--因为多了
printf("\n");
}
return 0; //这里也要加一个返回语句
}
下面再提供一个按你的思路写的比较精简一些的,供参考。
void main(void){/*主程序*/
int data,i=0,k,dx=0,dxx=0;
char a[16] = {0};
printf("输入一个十进制数");
scanf("%d",&data);
printf("OX");
if(data<0) dx=dxx=1;//设立负数标记
data=abs(data);
do{//变成十六进制数.但不是字符
a[i++]=data%16;
data=data/16;
}while(data);
k=i;

if(dxx==1)//负数时求反
for(i--;i>=0;i--) a[i]=~a[i]&0xF;

for(i=0;i<k;i++){//负数时加1与变为十六进制字符
if(a[i]==15){//解决进位情况
a[i]+=dx;
a[i]='0';
dx=dxx;
}
else{//无进位的情况
a[i]+=dx;
if(a[i]>=0 && a[i]<10) a[i]+='0';
else a[i]+=0x37;//
dx=0;
}
}
while(k!=0) printf("%c",a[--k]);//
printf("\n");
}

热心网友 时间:2023-12-07 14:46

在计算机中以二进制补码形式存放整数,使用%x可以看出整数的16禁制形式,机器码中没有正负之分,都以01来存放,辨别正负在于最高位是否为1
负数的补码为正数取反+1,最高位存一来显示
如,-5
5 的二进制为00000101
取反为01111010
取反+1之后为01111011,最高位+1为 11111011 使用16进制显示为0xfb
1、为何一个整数+'0',等于字符?
因此数字字符在ascii中为48~57,因此如果小于10的整数需要+48,才能以显示数字字符
2、对于data小于0的数据进行按字节取反应该对整数0~15进行取反,而当第一个do-while循环完成之后,数组里的数据都变为大于整数48的字符,
因此取反的时候,会对ascii码对应得整数进行取反,而得不到想要的结果

建议:(仅仅建议)
可以先把data%16之后的整数存储到数组中,再对数组中的每个数值进行取反,再输出整个数组。

if(data<0)//计算负数的十六进制
{
do
{
k = (abs(data)%16);
a[i] = k;
data=(abs(data))/16;
i++;
}while(data);
//首先把整数存储
//再把数组中每个数值取反
j = 16;
i = 0;
while(i!=16)
{
i==0 ? (k = (~a[i]+1)&0xf): (k=(~a[i]&0xf));//条件运算符,如果是第一个字符,取反+1,如果不是仅做取反
switch(k)
{
case 10:a[i]='A';break;
case 11:a[i]='B';break;
case 12:a[i]='C';break;
case 13:a[i]='D';break;
case 14:a[i]='E';break;
case 15:a[i]='F';break;
default:a[i]=k%16+'0';break;
}
i++;
}

while(j-->-1)
printf("%c",a[j]);
printf("\n");
}

热心网友 时间:2023-12-07 14:47

输出16进制数直接用%x即可,何必这样麻烦的去转?这不多此一举吗?追问不喜欢

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com