到目前为止我有这个代码:
for ( int i = 16; i >=0; i--){
int k = n >> i;
if (k & 1)
printf("1");
else
printf("0");
}
我是C的新手,我正在研究一个类的十进制到二进制转换器。到目前为止,这是我发现在我的参数范围内工作。唯一的问题是我需要这个代码才能将二进制文件输出到它给出的MSD。
如果我有十进制15,它应该以二进制显示1111,如果我有十进制16,它应该只显示上面的下一组4,所以00010000。
到目前为止,我可以将数量设置为我想要的数量,如i = 16,但总共会显示15个空格。好像我输入一个小十进制,我不希望我的程序显示所有额外的不必要的0。
那么有没有办法限制二进制输出以对应准确显示其转换所需的最重要空间?
一种方法是使用标志变量来检查我们是否具有非零msb,并且仅在我们遇到非零msb之后才开始打印0。
int flag
for ( int i = 16; i >=0; i--)
{
int k = n >> i;
if (k & 1){
printf("1");
flag = 1;
}else{
if(flag)
printf("0");
}
要以4个为一组对其进行排序,您需要轻咬半字节。打印半字节(值为0到15 dec)的函数可能如下所示:
void print_bin_nibble (uint8_t ls_nibble)
{
for(size_t i=0; i<4; i++)
{
uint8_t bitmask = 1u << (4-1-i);
printf("%c", (ls_nibble & bitmask) ? '1' : '0');
}
printf(" ");
}
现在,如果你想轻轻打印数据,同时跳过等于0000 bin的半字节的前导零,你需要跟踪是否应该跳过带有布尔标志的打印。逻辑是:
if(nibble==0 && remove_zeroes)
{
; // do nothing
}
else
{
remove_zeroes = false;
print_bin_nibble(nibble);
}
哪些可以改写为(德摩根定律):
if(nibble != 0 || !remove_zeroes)
{
remove_zeroes = false;
print_bin_nibble(nibble);
}
打印数字时的进一步考虑是CPU结束。我们可以使用各种(坏)方法逐字节地迭代整数,例如使用指针算术或联合。但随后输出将依赖于endianess并且在小端机器上看起来很奇怪。通过使用位移,我们完全消除了这个可移植性问题,因为它们与endianess无关。
例如,给定32位整数u32,我们可以屏蔽掉各个字节,如下所示:
(u32 >> (24-n*8)) & 0xFF
其中n
是字节数0到3.我们最终为n = 0移位24位,n = 1时为16位,n = 2时为8位,n = 3时为0位。
完整示例:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
void print_bin_nibble (uint8_t ls_nibble)
{
for(size_t i=0; i<4; i++)
{
uint8_t bitmask = 1u << (4-1-i);
printf("%c", (ls_nibble & bitmask) ? '1' : '0');
}
printf(" ");
}
void print_bin32 (uint32_t u32)
{
bool remove_zeroes = true;
for(size_t i=0; i<sizeof(u32); i++)
{
uint8_t byte = (u32 >> (24-i*8)) & 0xFF;
uint8_t nibble;
nibble = (uint32_t)byte >> 4;
if(nibble != 0 || !remove_zeroes)
{
remove_zeroes = false;
print_bin_nibble(nibble);
}
nibble = byte & 0xF;
if(nibble != 0 || !remove_zeroes)
{
print_bin_nibble(nibble);
}
}
printf("\n");
}
int main (void)
{
print_bin32(16);
print_bin32(0xDEADBEEF);
print_bin32(0xABBA);
}
输出:
0001 0000
1101 1110 1010 1101 1011 1110 1110 1111
1010 1011 1011 1010