几天前我问了一个问题,这对我有很大帮助,但是我又有一个问题。我没有得到的是当我获得十六进制输入作为scanf(“%c%c。%c%c。%c%c。%c%c%c”)时如何将其原样转换为二进制。我要说的是,假设我输入为00.11.10.FF,如何将其转换为00000000.00010001.0001000010000.11111111并像这样打印它。
如果您能帮助我,我会很高兴。
答案 0 :(得分:2)
如果仍然有问题(如注释中所述),除非要创建查找表(这是一种很好的方法),否则您的第一个任务是将ASCII字符"00.11.10.FF"
转换为0x0, 0x11, 0x10 & 0xff
的实际数值。有多种方法可以执行此操作,但是如果您使用scanf
阅读,也可以使用scanf
格式说明符阅读,让"%x"
为您完成此操作十六进制字符并执行转换。
例如,要将每个四边形读入名为unsigned
的{{1}}个值的数组中,可以执行以下操作:
hex
(注意:,您可以将#define QUAD 4u /* if you need a constant, #define one (or more) */
...
unsigned hex[QUAD] = {0}; /* let's input the values as numbers */
...
if (scanf ("%x.%x.%x.%x", &hex[0], &hex[1], &hex[2], &hex[3]) != 4) {
fputs ("error: invalid input.\n", stderr);
return 1;
}
声明为hex
并保存其他字节,但是随后您想限制unsigned char
使用的值scanf
type-modifier ,例如hh
,但是在较早版本的VS中不支持该前缀,因此在这种情况下使用简单的"%hhx"
代替
将十六进制字符转换为数值后,剩下的就是输出每个数字的二进制表示形式(即已经存储在内存中的值)。为此,您可以简单地循环和移位,检查该位是unsigned
还是0
,然后输出相应的字符1
或'0'
。
此外,由于仅在没有剩余'1'
位的情况下才会输出简单的循环和移位,因此您将需要设置要显示的位数,以确保每字节获得完整的8位通过循环该次数。将请求的位数写入信息到1's
的便捷功能可以是:
stdout
({/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 1 - sizeof v * CHAR_BIT.
*/
void binprnpad (const unsigned long v, size_t sz)
{
if (!sz) { fprintf (stderr, "error: invalid sz.\n"); return; }
if (!v) { while (sz--) putchar ('0'); return; }
if (sz > sizeof v * CHAR_BIT)
sz = sizeof v * CHAR_BIT;
while (sz--)
putchar ((v >> sz & 1) ? '1' : '0');
}
是一个宏,代表每字节的位数,可以在CHAR_BIT
中找到)
完全将其放入,您可以这样做:
limits.h
使用/输出示例
#include <stdio.h>
#include <limits.h>
#define QUAD 4u /* if you need a constant, #define one (or more) */
#define QBITS 8u
/** 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) { fprintf (stderr, "error: invalid sz.\n"); return; }
if (!v) { while (sz--) putchar ('0'); return; }
if (sz > sizeof v * CHAR_BIT)
sz = sizeof v * CHAR_BIT;
while (sz--)
putchar ((v >> sz & 1) ? '1' : '0');
}
int main (void) {
unsigned hex[QUAD] = {0}; /* let's input the values as numbers */
fputs ("enter hex IP: ", stdout); /* read/validate input */
if (scanf ("%x.%x.%x.%x", &hex[0], &hex[1], &hex[2], &hex[3]) != 4) {
fputs ("error: invalid input.\n", stderr);
return 1;
}
for (unsigned i = 0; i < QUAD; i++) { /* loop over each quad */
if (i) /* if not zero output the '.' */
putchar ('.');
binprnpad (hex[i], QBITS); /* output the 8-bits per quad */
}
putchar ('\n'); /* tidy up with newline */
return 0;
}
只读字符-查找表方法
如果您只能读取字符而不能读取数组或字符串,那么最简单的方法是简单地读取字符并从保存{{1}的二进制表示形式的简单表中查找其二进制表示形式。 }(或$ ./bin/hexip2bin
enter hex IP: 00.11.10.FF
00000000.00010001.00010000.11111111
)。
查找表可以是简单的全局变量,例如
0 - 15
然后该方案很简单,从用户那里读取一个字符,如果字符[0-9A-F]
是/* lookup table for hex byte binary representations */
char *lookup[] = { "0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111" };
,则只输出c
(其中0-9
产生数字lookup[c - '0']
参见:ASCIITable.com)。如果字符c - '0'
为0-9
,则输出c
(将[A-F]
的ASCII字符值减去以查找表中的索引lookup[c - '7']
)。否则,如果字符是'7'
,则将其原样输出。
要防止有人输入10-15
,只需使用'.'
中提供的"00.11.10.ff"
将所有读取的字符转换为大写字母即可(或手动清除所有toupper()
中的第6位)。
就这么简单。您甚至不需要ctype.h
,例如[a-f]
scanf
使用/输出示例
getchar();
小写十六进制示例:
#include <stdio.h>
#include <ctype.h>
#define QBYTES 8u /* if you need a constant, #define one */
/* lookup table for hex byte binary representations */
char *lookup[] = { "0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111" };
int main (void) {
unsigned ndx = 0; /* index of the hex byte read */
fputs ("enter hex IP: ", stdout); /* read/validate input */
while (ndx < QBYTES) { /* read until 8 hex bytes read */
unsigned char c = toupper(getchar()); /* read char as upper-case */
if (isdigit (c)) { /* if [0-9] */
fputs (lookup[c - '0'], stdout);
ndx++; /* increment index */
}
else if (isxdigit (c)) { /* if [A-F] */
fputs (lookup[c - '7'], stdout);
ndx++;
}
else if (c == '.') /* if '.' */
putchar (c);
else { /* handle character not [0-9A-F.] */
fputs ("(error: invalid character input)\n", stderr);
break;
}
}
putchar ('\n'); /* tidy up with newline */
return 0;
}
读取一个$ ./bin/hexip2bin
enter hex IP: 00.11.10.FF
00000000.00010001.00010000.11111111
输出一个半字节
当然,您始终可以在方法之间进行混合和匹配。如果您不能使用 lookup-table ,则只需获取字符的数值,然后将表示该十六进制值的4位写为输出即可,例如
$ ./bin/hexip2bin
enter hex IP: 00.11.10.ff
00000000.00010001.00010000.11111111
(输出相同)
这是给同一只猫剥皮的另一种方法。仔细研究一下,如果您还有其他问题,请告诉我。