这是一个家庭作业,我必须在终端中调用命令时将十六进制转换为二进制 . 我的“老师”并不真正“教”C,所以我迷路了 . 我必须包含一个过程,void printBits(unsigned long i),它打印i中的位 . 它将使用'-p'开关从命令行调用,后跟一个十六进制形式的32位无符号长整数 . EX:$ lab3 -p 0x5
输出:0000 0000 0000 0000 0000 0000 0000 0101
请不要只给我代码 . 我需要了解这一点 .
void printBits(unsigned long number) {
// Declare Array to hold our binary number
char binaryNumber[32];
// For Loop Index
int i;
for (i = 31; i >= 0; --i)
{
binaryNumber[i] = (number & 1);
number >>= 1;
}
4 回答
有许多方法可以为任何数字打印二进制表示 . 首先,你可以直接输出你的移位和索引操作的结果(到
stdout
,一个文件等...)这似乎是你开始的方法,但后来你声明了一个32位缓冲区 . 虽然您当然可以这样做,但如果您不打算返回指向已完成缓冲区的指针,则无需缓冲结果 . (这让我想到了我的第3点,下面)简单地输出比特而不存储/返回指向以空字符串终止的字符串中的比特的指针,它具有其位置,但通常使用有限 . 然而,这是一个包含所有方法基础的常见问题 . 可以按如下方式创建未填充的二进制表示:
评论相当明确 . 该方案是将每个位从最高有效位开始移位(例如,位31(31-0)为32位数 . 检查移位后是否有任何1位(如果不是,则移位超过最大位)数字中的有效位位置,无需打印) . 一旦在
rem
中找到一个位,在循环迭代的其余部分中始终会有位位打印,因为您正在减少量 . 最重要的位(首先打印),最终会以正确的顺序打印出您的位,并且只打印构成该位数的位数 .通常,当您只是将二进制表示直接输出到屏幕时,您只需要输出最高位的位 . (这可以防止输出一个
1
,其前面有630
的东西 . )接下来,将填充的二进制表示输出到某个位数 . 如果您只想查看任何数字中较低的
8, 16, 32, ...
位,但希望每次都有一个固定位数的表示,这非常有用 . 在这里,您只需传递您想要查看的位数 . 然后,您的函数将循环遍历数字中的位数并输出结果:您会注意到这里的主要区别在于您不必关心是否保留位以防止打印不需要的前导零,因为您使用参数
sz
控制位数 . (如果传递了0
尺寸,那取决于你做什么,我只选择输出'0'
)现在为上面提到的第三点 . 从代码主体中的格式化角度来看,简单地输出位是很麻烦的 . 我发现将这些位存储在一个字符数组中是非常有用的(nul-terminated所以它可以被视为一个字符串)并返回一个指向数组的指针,因此它可以传递给
printf
等 . 现在你要么必须通过一个足够大小的数组作为参数,声明一个static
数组,以便在函数返回时不销毁该数组,或者为该函数内的数组动态分配存储 . 根据代码的需要,你必须权衡所有的优点和缺点 . 例如 . :该代码的功能与上面的非缓冲填充对应的功能相同 . 注意
p
如何返回sz
位开始的缓冲区内的起始位置 . 另请注意,您需要一个常量BITS_PER_LONG
表示硬件上long
的位数 . (通常以类似BUILD_64
的方式处理)note: 只要知道
static
声明的一个限制是转换函数只能在任何一个printf
调用中使用一次(或在任何一行代码中使用),因为二进制转换只有一个存储阵列 . (您可以随时拨打任意号码并将结果存储在拨打printf
之前的不同位置)二进制打印的最后一个变体是打印包含分隔符的表示,以便更容易识别和比较二进制字符串(特别是在处理
0
和_712924的较长序列时 . 例如:该函数基本上与上面的
binpad
相同,但添加了静态缓冲区以容纳分隔符,并额外检查位位置以确定何时应将分隔符添加到缓冲区:剩下的你的问题只是处理命令行参数,并执行从输入字符串到无符号值的转换以及数字不超过32位的验证检查等 . 您可以使用
getops
或小的处理参数您可以简单地使用循环的简单选项的数量 . 在Linux上,代码应该响应的唯一必需参数是-h
表示帮助,-v
表示版本 . 虽然没有人为简短的例子等做这件事,但获得这些信息至少是好的 . 查看以下将所有部分放在一起的示例,如果您有任何疑问,请告诉我:Use/Output
每个棕色都作为一系列位存储在机器中 . 要将它们打印到控制台,您需要传递一个字符串,其中每个字符为1(0x31)或0(0x30),具体取决于是否设置了相应的数字位 . 最后一个字符必须是'\ 0'才能表示字符串的结尾 .
在准备好字符缓冲区后,可以使用例如将它们打印到控制台 .
fprintf
:稍微纠正你的代码,以确保字符串是NULL终止(它有'\ 0'作为缓冲区中的最后一个字符),你把字符放入缓冲区(否则1和0不是可打印的字符放入缓冲区,你会看到完全没有输出):
打印:
编号00000000000000000000000000000001
编号00000000000000000000000000000010
编号00000000000000000000000000001111
编号00000000000000000000000001111111
编号00000000000000000000000100000000
编号00000000000000000011000000111001
首先,将从命令行获取的字符串转换为整数,最简单的方法是使用sscanf
例如
现在你有十进制值
n
.要转换为二进制,您需要遍历无符号整数中的每个位 .
通过按位和小数值,您可以检查每个位是否已设置并打印“1”或“0”,具体取决于位
这里's one way your program could look. I' ve评论了重要的部分,但是你必须查看正在使用的函数的文档 . 如果您正在使用linux(看起来您正在判断原始问题)那么您可以使用linux "manual pages"(例如
man sscanf
)来提供有关sscanf或C库中任何其他函数的完整信息 .编译它:
gcc main.c -o lab3
我自己写了这个,但网上有很多这种“教学练习”的例子,所以我认为在这里只包括逐字代码并不是一个扰流 .