Если у вас все еще есть проблемы, как объясняется в комментариях, если вы не хотите создавать справочную таблицу (это хороший способ), ваша первая задача - преобразовать символы 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;
}
(вывод такой же)
Просто еще один способ снять шкуру с той же кошки. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.