Почему этот код работает для преобразования шестнадцатеричного в десятичное - PullRequest
2 голосов
/ 23 февраля 2011

Этот код преобразует одну шестнадцатеричную цифру в десятичное значение.

int value;
// ch is a char variable holding a hexadecimal digit
if (isxdigit(ch))
    if (isdigit(ch))
        value = ch - '0';
    else
        value = tolower(ch) - 'a' + 10;
else
    fprintf(stderr, "%c is not a valid hex digit", ch);

Я не до конца понимаю, как это работает. Я вижу, что разные вещи вычитаются из переменной char в зависимости от того, является ли это число или буква. Я могу понять ту часть, где число конвертируется, но я не понимаю, почему к значению нужно добавить 10, когда символ является буквой.

Ответы [ 2 ]

11 голосов
/ 23 февраля 2011

Вычитание tolower(ch) - 'a' отобразит символ в число в диапазоне 0..5 для букв a..f.Однако (десятичное) значение шестнадцатеричной цифры a 16 равно 10 10 , поэтому для перемещения диапазона обратно до 10..15, где это необходимо, добавляется 10.

Возможно, это поможет:

+---------+------------+-----------------+-------------+
Character | Subtracted | Resulting value | Digit value |
+---------+------------+-----------------+-------------+
|   '0'   |     '0'    |       0         |       0     |
|   '1'   |     '0'    |       1         |       1     |
|   '2'   |     '0'    |       2         |       2     |
|   '3'   |     '0'    |       3         |       3     |
|   '4'   |     '0'    |       4         |       4     |
|   '5'   |     '0'    |       5         |       5     |
|   '6'   |     '0'    |       6         |       6     |
|   '7'   |     '0'    |       7         |       7     |
|   '8'   |     '0'    |       8         |       8     |
|   '9'   |     '0'    |       9         |       9     |
|   'a'   |     'a'    |       0         |      10     |
|   'b'   |     'a'    |       1         |      11     |
|   'c'   |     'a'    |       2         |      12     |
|   'd'   |     'a'    |       3         |      13     |
|   'e'   |     'a'    |       4         |      14     |
|   'f'   |     'a'    |       5         |      15     |
+---------+------------+-----------------+-------------+

Обратите внимание, что столбец «результирующее значение» сбрасывается обратно в 0 в «a», а это не то место, где он должен быть в соответствии с финалом »цифра "столбец, который показывает значение каждой шестнадцатеричной цифры в десятичном виде.

1 голос
/ 23 февраля 2011

Выражение ch - '0' работает, потому что в C "значение каждого символа после 0 ... должно быть на единицу больше, чем значение предыдущего" ( C99 раздел 5.2.1).

Так, например, значение символа '3' на 3 больше значения '0', поэтому при вычитании этих двух значений вы получите целое число 3.

Выражениеtolower(ch) - 'a' + 10 работает по счастливой случайности, потому что, за исключением вышеуказанного ограничения для цифр, все значения символов определяются реализацией.

Таким образом, когда вы вычитаете 'c' - 'a', вы получаете 2 (и, добавляя 10, вы получаете12 - правильное значение этой цифры), потому что большинство компьютеров работают в ASCII или EBCDIC.Но когда вы запускаете эту программу на DS9K, вы можете получить −42.

Чтобы быть действительно переносимым, вам нужно сравнить ch с каждой из шести букв по очереди.Вот почему некоторые системы предоставляют функцию digittoint().

...