Преобразование шестнадцатеричного IP-символа в двоичный - PullRequest
0 голосов
/ 17 марта 2019

Я задал вопрос несколько дней назад, и это мне очень помогло, но у меня снова возник вопрос. То, что я не получаю, это когда я получаю шестнадцатеричный ввод как scanf ("% c% c.% C% c.% C% c.% C% c% c"), как мне преобразовать это в двоичный файл как есть. То, что я пытаюсь сказать, скажем, я получаю ввод как 00.11.10.FF, как мне преобразовать его в 00000000.00010001.00010000.11111111 и напечатать его следующим образом.

Буду рад, если вы мне поможете.

1 Ответ

2 голосов
/ 17 марта 2019

Если у вас все еще есть проблемы, как объясняется в комментариях, если вы не хотите создавать справочную таблицу (это хороший способ), ваша первая задача - преобразовать символы ASCII "00.11.10.FF" в действительные числа значения 0x0, 0x11, 0x10 & 0xff. Есть несколько способов сделать это, но если вы читаете с scanf, вы также можете позволить scanf сделать это за вас, прочитав спецификатор формата "%x", который будет принимать шестнадцатеричные символы и выполнять конверсия.

Например, чтобы прочитать каждый из четырех квадратов в массив unsigned значений с именем 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, используя hh модификатор типа , например "%hhx", но этот префикс не поддерживается в более старых версиях VS, поэтому в этом случае вместо него используется простой unsigned)

С шестнадцатеричными символами, преобразованными в числовые значения, все, что остается, - это выводить двоичное представление каждого (то есть значение, которое уже сохранено в памяти). Для этого вы можете просто выполнить цикл и сдвиг, проверяя, является ли бит 0 или 1 и выводя соответствующий символ '0' или '1'.

Кроме того, поскольку простой цикл и сдвиг будут выводиться только до тех пор, пока не останется больше 1's битов, вам нужно установить количество отображаемых битов, чтобы убедиться, что вы получите полный 8-байтный цикл это количество раз. Удобная функция для записи информации в 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;
}

Пример использования / Вывод

$ ./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'] (где c - '0' приводит к числу 0-9 См .: ASCIITable.com ). Если символ c равен [A-F], выведите lookup[c - '7'] (который вычитает значение символа ASCII '7' для индекса 10-15 в таблице поиска). В противном случае, если символ является '.', просто выведите его без изменений.

Чтобы защитить кого-то от ввода "00.11.10.ff", просто преобразуйте все прочитанные символы в случайный случай с toupper(), указанным в ctype.h (или сбросьте 6-й бит во всех [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

Пример шестнадцатеричного регистра в нижнем регистре:

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

Чтение A char Выход A Клев

И, конечно, вы всегда можете смешивать и сочетать методы. Если вы не можете использовать справочную таблицу , то просто получите числовое значение символа и запишите 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;
}

(вывод такой же)

Просто еще один способ снять шкуру с той же кошки. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...