gpt4 book ai didi

c - 从命令行参数C将十六进制转换为二进制

转载 作者:太空宇宙 更新时间:2023-11-04 03:32:11 24 4
gpt4 key购买 nike

这是一个家庭作业,在终端调用命令时,我必须将十六进制转换为二进制。我的“老师”不是真正的“老师”,所以我完全迷路了。我必须包含一个过程void printBits(unsigned long I),它在I中打印位。它将使用'-p'开关从命令行调用,后跟一个32位的十六进制无符号长整数。示例:$lab3-p 0x5
产量: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;
}

最佳答案

有很多方法可以打印任何数字的二进制表示。首先,您可以直接输出移位和索引操作的结果(到stdout,一个文件,等等…)。这似乎是您开始使用的方法,但随后您声明了一个32位缓冲区。虽然您当然可以这样做,但如果不返回指向已完成缓冲区的指针,则不需要缓冲结果。(这就引出了我下面的第三点)
简单地输出位而不存储/返回指向以nul结尾的字符串中的位的指针,有它的位置,但通常用途有限。然而,这是一个共同的问题,包含了所有方法的基础。创建未添加的二进制表示法的方法如下:

/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; }; /* if v = 0 output '0' */

size_t sz = sizeof v * CHAR_BIT; /* get the number of bits in v */
unsigned long rem = 0; /* variable to hold shifted result */

while (sz--) /* for each bit (in decreasing order) */
if ((rem = v >> sz)) /* if bits exist in the shifted value */
putchar ((rem & 1) ? '1' : '0'); /* output '1' or '0' */
}

这些评论很有解释性。该方案是以32位数字的最高有效位(例如,位31(31-0))开始移动每个位。检查移位后是否有任何1位(如果没有,则移位超过数字中最有效的位位置,无需打印)。一旦在 rem中找到一个位,在循环迭代的其余部分中总会有位要打印,因为您正在以递减的量移动。从最有意义的位开始(首先打印),你的位以正确的顺序打印出来,并且只打印组成这个数字的位数。
通常,当您只是直接将二进制表示输出到屏幕时,您只希望输出最高有效位的位。(这可以防止输出一个前面有63个“cc>”的“a 1”,使事情变得一团糟。)
下一步,是将填充的二进制表示输出到一些位。如果您只想查看任意数字中较低的 0位,但希望每次都有固定位数的表示,那么这非常有用。在这里,您只需传递希望查看的位数。然后,您的函数将循环遍历您的数字中的位数位置,并输出结果:
/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binprnpad (const unsigned long v, size_t sz)
{
if (!sz) putchar ((v & 1) ? '1' : '0'); /* if no sz, '0' is fine */

if (sz > sizeof v * CHAR_BIT) /* if sz exceed # of bits, limit */
sz = sizeof v * CHAR_BIT;

while (sz--) /* for sz positions in decreasing order, '1' or '0' */
putchar ((v >> sz & 1) ? '1' : '0');
}

您将注意到这里的主要区别是,您不必担心检查位是否保留以防止打印不需要的前导零,因为您使用参数 8, 16, 32, ...控制位的数量。(如果通过 sz大小,由您决定如何操作,我只选择输出 0
现在谈上面提到的第三点。从代码主体的格式化角度来看,简单地输出位是很麻烦的。我发现将位存储在字符数组中(以nul结尾,因此可以将其视为字符串)并返回指向数组的指针,以便将其传递给 '0'等更有用。现在,您要么必须将大小适当的数组作为参数传递,声明 printf数组,以便在函数返回时不会破坏数组,或者为函数内的数组动态分配存储空间。所有这些都有优缺点,根据代码的需要,您必须权衡它们。例如。:
/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;

for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';

return p;
}

代码的功能与上面的非缓冲填充对应代码相同。注意 static如何返回缓冲区中 p位数开始的起始位置。还要注意,您需要一个常量来表示硬件上a sz中的位数。(通常以类似于 BITS_PER_LONG的方式处理)
注意:只需注意,对 long声明的一个限制是转换函数在任何一个 BUILD_64调用中(或在任何一行代码中)只能使用一次,因为只有一个存储数组用于二进制转换。(在进行 static调用之前,您始终可以进行任意数量的调用,并将结果存储在不同的位置)
二进制打印的最后一个变化是使用包含分隔符的打印表示,以便更容易识别和比较二进制字符串(特别是在处理较长的 printfprintf序列时。例如:
hexval : 0xdeadbeef  =>  11011110-10101101-10111110-11101111

该函数的工作原理与上面的 0基本相同,但添加了静态缓冲区以容纳分隔符,并额外检查位位置以确定何时应向缓冲区添加分隔符:
/** returns pointer to formatted binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep)
{
static char s[BITS_PER_LONG * 2 + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
register size_t i;

*p = 0;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (v >> i & 1) ? '1' : '0';
}

return p;
}

问题的其余部分只是处理命令行参数,并执行从输入字符串到无符号值的转换,以及验证该数字是否不超过32位等。。您可以使用 1处理参数,也可以使用循环处理少量简单选项。在Linux上,您的代码应该响应的唯一必需参数是 binpad以获取帮助,而 getops以获取版本。虽然没有人这样做的简短例子等,它至少是好的,有这些信息。请看下面的示例,它将所有部分组合在一起,如果您有任何问题,请告诉我:
#include <stdio.h>
#include <stdlib.h> /* for strtoul */
#include <errno.h> /* for errno */
#include <limits.h> /* for UINT_MAX, ULONG_MAX, CHAR_BIT */

#define PACKAGE "hex2bin"
#define VERSION "0.01"

/* BUILD_64 - Check x86/x86_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif

/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif

unsigned long processopts (int argc, char **argv);
unsigned long xstrtoul (char *s);
void binprn (const unsigned long v);
void binprnpad (const unsigned long v, size_t sz);
char *binpad (const unsigned long v, const size_t sz);
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep);
void help (int xcode);

int main (int argc, char **argv) {

unsigned long hexval = processopts (argc, argv);

/* print unpadded binary */
printf ("\n hexval : 0x%lx (%lu) => ", hexval, hexval);
binprn (hexval);
printf ("\n");

/* print padded to 32-bits */
printf ("\n hexval : 0x%lx (%lu) => ", hexval, hexval);
binprnpad (hexval, sizeof (int) * CHAR_BIT);
printf ("\n");

/* padded binary returned as formatted string
* with '-' separators every 8 bits
*/
printf ("\n hexval : 0x%lx (%lu) => %s\n\n", hexval, hexval,
binfmt (hexval, sizeof (int) * CHAR_BIT, CHAR_BIT, '-'));

return 0;
}

/* quick custom argument handler */
unsigned long processopts (int argc, char **argv)
{
size_t i = 1;
unsigned long val = 0;

if (argc < 2) help (0); /* insufficient arguments */

for (; argv[i]; i++) { /* for each argument */
if (*argv[i] == '-') { /* for each beginning with '-' */
switch (argv[i][1]) {
case 'h': /* respond to '-h' help */
help (0);
case 'p': /* handle '-p' convert value */
if (!argv[i+1]) { /* if '-p' w/o next arg */
fprintf (stderr, "error: insufficient input.\n");
help (1);
}
if (*argv[i+1] != '0' || /* validate hex input */
(argv[i+1][1] != 'x' && argv[i+1][1] != 'X')) {
fprintf (stderr, "error: invalid 'hex_value' input.\n");
help (1);
}
val = xstrtoul (argv[i+1]); /* convert to ulong */
if (val > UINT_MAX) { /* validate 32-bits */
fprintf (stderr, "error: input value exceeds 32-bits.\n");
help (1);
}
break;
case 'v': /* respond to '-v' version */
printf ("%s, version %s\n", PACKAGE, VERSION);
exit (0);
default :
fprintf (stderr, "error: invalid/unrecognized option '%s'.\n",
argv[i]);
help (1);
}
}
}
return val; /* return val */
}

unsigned long xstrtoul (char *s)
{
unsigned long v = 0;
errno = 0;

/* test for hex or decimal conversion */
if (*s == '0' && (s[1] == 'x' || s[1] == 'X'))
v = strtoul (s, NULL, 16);
else
v = strtoul (s, NULL, 10);

/* check for various possible errors */
if ((errno == ERANGE && v == ULONG_MAX) || (errno != 0 && v == 0)) {
perror ("strtoul");
exit (EXIT_FAILURE);
}
return v;
}

/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; };

size_t sz = sizeof v * CHAR_BIT;
unsigned long rem = 0;

while (sz--)
if ((rem = v >> sz))
putchar ((rem & 1) ? '1' : '0');
}

/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binprnpad (const unsigned long v, size_t sz)
{
if (!sz) putchar ((v & 1) ? '1' : '0');

if (sz > sizeof v * CHAR_BIT)
sz = sizeof v * CHAR_BIT;

while (sz--)
putchar ((v >> sz & 1) ? '1' : '0');
}

/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;

for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';

return p;
}

/** returns pointer to formatted binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep)
{
static char s[BITS_PER_LONG * 2 + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
register size_t i;

*p = 0;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (v >> i & 1) ? '1' : '0';
}

return p;
}

void help (int xcode)
{
xcode = xcode ? xcode : 0; /* set default exit code */

printf ("\n %s, version %s\n\n"
" usage: %s -p hex_value (32-bit)\n\n"
" converts 'hex_value' to its binary representation.\n\n"
" Options:\n\n"
" -h this help.\n"
" -p hex_value display binary representation of 'hex_value'.\n"
" -v display version information.\n\n",
PACKAGE, VERSION, PACKAGE);

exit (xcode);
}

使用/输出
$ ./bin/hex2bin -p 0xe7

hexval : 0xe7 (231) => 11100111

hexval : 0xe7 (231) => 00000000000000000000000011100111

hexval : 0xe7 (231) => 00000000-00000000-00000000-11100111


$ ./bin/hex2bin -p 0xdeadbeef

hexval : 0xdeadbeef (3735928559) => 11011110101011011011111011101111

hexval : 0xdeadbeef (3735928559) => 11011110101011011011111011101111

hexval : 0xdeadbeef (3735928559) => 11011110-10101101-10111110-11101111


$ ./bin/hex2bin -h

hex2bin, version 0.01

usage: hex2bin -p hex_value (32-bit)

converts 'hex_value' to its binary representation.

Options:

-h this help.
-p hex_value display binary representation of 'hex_value'.
-v display version information.


$ ./bin/hex2bin -v
hex2bin, version 0.01

关于c - 从命令行参数C将十六进制转换为二进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35500171/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com