将十六进制char IP转换为二进制

时间:2019-03-17 02:13:51

标签: c

几天前我问了一个问题,这对我有很大帮助,但是我又有一个问题。我没有得到的是当我获得十六进制输入作为scanf(“%c%c。%c%c。%c%c。%c%c%c”)时如何将其原样转换为二进制。我要说的是,假设我输入为00.11.10.FF,如何将其转换为00000000.00010001.0001000010000.11111111并像这样打印它。

如果您能帮助我,我会很高兴。

1 个答案:

答案 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

(输出相同)

这是给同一只猫剥皮的另一种方法。仔细研究一下,如果您还有其他问题,请告诉我。