简体   繁体   English

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

[英]Converting hexadecimal char IP to binary

I asked a question few days ago and it helped me quite a bit but yet I have a question again. 几天前我问了一个问题,这对我有很大帮助,但我又有一个问题。 What I don't get is when I get hexadecimal input as scanf("%c%c.%c%c.%c%c.%c%c%c") how do I convert this to binary as it is. 我没有得到的是当我获得十六进制输入作为scanf(“%c%c。%c%c。%c%c。%c%c%c”)时如何将其原样转换为二进制。 What I'm trying to say is let's say I get input as 00.11.10.FF how do I convert it to 00000000.00010001.00010000.11111111 and print it like this. 我要说的是,假设我将输入输入为00.11.10.FF,如何将其转换为00000000.00010001.00010000.11111111并像这样打印。

I will be glad if you help me. 如果您能帮助我,我会很高兴。

If you are still having problems, as explained in the comments, unless you want to create a lookup-table (which is a fine way to go), your first task is to convert the ASCII characters "00.11.10.FF" into actual numeric values of 0x0, 0x11, 0x10 & 0xff . 如果仍然有问题(如注释中所述),除非要创建查找表(这是一种很好的方法),否则您的第一个任务是将ASCII字符"00.11.10.FF"转换为实际的0x0, 0x11, 0x10 & 0xff数值。 There are a number of ways to do this, but if you are reading with scanf , you may as well let scanf do it for you by reading with the "%x" format specifier which will accept the hex-characters and perform the conversion. 有多种方法可以执行此操作,但是如果您正在使用scanf进行读取,则最好通过使用"%x"格式说明符进行读取来让scanf为您完成此操作,该格式说明符将接受十六进制字符并执行转换。

For example, to read each of the quads into an array of unsigned values named hex , you could do: 例如,要将每个四边形读入一个名为hexunsigned值的数组,可以执行以下操作:

#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;
    }

( note: you could declare hex as unsigned char and save the additional bytes, but then you would want to limit the value read by scanf using the hh type-modifier , eg "%hhx" , but that prefix isn't supported on older versions of VS, so in this case a simple unsigned is used instead) 注意:您可以将hex声明为unsigned char并保存其他字节,但是随后您想使用hh type-modifier来限制scanf读取的值,例如"%hhx" ,但是较早版本不支持该前缀VS版本,因此在这种情况下,使用简单的unsigned代替)

With the hex-characters converted to numeric values, all that remains is outputting the binary-representation of each (ie the value that is already stored in memory). 将十六进制字符转换为数值后,剩下的就是输出每个数字的二进制表示形式(即,已经存储在内存中的值)。 To do so, you can simply loop and shift, checking whether the bit is a 0 or 1 and outputting the corresponding character '0' or '1' . 为此,您可以简单地循环和移位,检查该位是0还是1然后输出相应的字符'0''1'

Additionally, since a simple loop and shift will only output until there are no more 1's bits left, you will want to set the number of bits to display to make sure you get a full 8-per-byte by looping that number of times. 此外,由于仅在没有剩余1's位的情况下才会输出简单的循环移位,因此您将需要设置要显示的位数,以确保通过循环该次数获得完整的每字节8位。 A handy function to write the information to stdout for the number of bits requested can be: 一个方便的功能,可以将信息写入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 is a macro representing the number of bits-per-byte and is found in limits.h ) CHAR_BIT是代表每字节位数的宏,可以在limits.h找到)

Putting it altogether, you could do: 综上所述,您可以执行以下操作:

#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;
}

Example Use/Output 使用/输出示例

$ ./bin/hexip2bin
enter hex IP: 00.11.10.FF
00000000.00010001.00010000.11111111

Reading Only Characters -- The Lookup Table Approach 只读字符-查找表方法

If you can only read characters and cannot read into an array or string, then the simplest approach is to simply read a characters and lookup what its binary representation would be from a simply table that holds the binary representations for 0 - 15 (or [0-9A-F] in other words). 如果您只能读取字符而不能读取数组或字符串,那么最简单的方法是简单地读取字符并从保存了0 - 15 (或[0-9A-F]的二进制表示形式的简单表中查找其二进制表示形式。 [0-9A-F] )。

The lookup table can be a simple global, eg 查找表可以是一个简单的全局表,例如

/* 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"  };

The scheme is then straight forward, read a character from the user, if the character c is 0-9 , just output lookup[c - '0'] (where c - '0' results in the number 0-9 See: ASCIITable.com ). 然后,该方案很简单,从用户那里读取一个字符,如果字符c0-9则只输出lookup[c - '0'] '0 lookup[c - '0'] (其中c - '0' '0 c - '0'结果为0-9请参见: ASCIITable .com )。 If the character c is [AF] then output lookup[c - '7'] (which subtracts the ASCII character value of '7' to index 10-15 in the lookup table). 如果字符c[AF]则输出lookup[c - '7'] (将ASCII字符值'7'减去以查找表中的索引10-15 )。 Otherwise, if the character is a '.' 否则,如果字符是'.' , just output it unchanged. ,只需输出不变即可。

To protect against someone entering "00.11.10.ff" , just convert all characters read to uppper-case with toupper() provided in ctype.h (or clear the 6th bit in all [af] manually). 为了防止有人输入"00.11.10.ff" ,只需使用ctype.h提供的toupper()将所有读取的字符转换为uppper-case(或手动清除所有[af]的第6位)。

That's as simple as it gets. 就这么简单。 You don't even need scanf , just getchar(); 您甚至不需要scanf ,只需要getchar(); , eg ,例如

#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;
}

Example Use/Output 使用/输出示例

$ ./bin/hexip2bin
enter hex IP: 00.11.10.FF
00000000.00010001.00010000.11111111

lower-case hex example: 小写十六进制示例:

$ ./bin/hexip2bin
enter hex IP: 00.11.10.ff
00000000.00010001.00010000.11111111

Read A char Output A Nibble 读一个char输出一个半字节

And, of course, you can always mix and match between the methods. 而且,当然,您始终可以在方法之间进行混合和匹配。 If you can't use a lookup-table , then just get the numeric value of the character and write the 4-bits representing that hex value as output, eg 如果您不能使用lookup-table ,则只需获取字符的数值并写入代表该十六进制值的4位作为输出即可,例如

#include <stdio.h>
#include <limits.h>
#include <ctype.h>

#define QUAD  4u    /* if you need a constant, #define one (or more) */
#define QBYTES 8u

/** 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');
}

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] */
            binprnpad (c - '0', QUAD);
            ndx++;
        }
        else if (isxdigit (c)) {                /* if [A-F] */
            binprnpad (c - '7', QUAD);
            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;
}

(output is the same) (输出是相同的)

Just another way of skinning the same cat. 这是给同一只猫剥皮的另一种方法。 Look things over and let me know if you have further questions. 仔细检查一下,如果您还有其他问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM