Лучший способ проверить, является ли цифра в конкретной базе в C - PullRequest
0 голосов
/ 13 февраля 2011

Я знаю, что ctype.h определяет isdigit, однако это работает только для базы 10. Я хотел бы проверить, является ли число цифрой в данной базе int b.

Какой лучший способ сделать это в C?

Редактировать

Я придумал следующую функцию:

int y_isdigit(char c, int b) {
        static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        static int digitslen = sizeof digits - 1;
        static int lowest = 0;
        int highest = b - 1;

        if(highest >= digitslen)
                return -1; /* can't handle bases above 35 */
        if(b < 1)
                return -2; /* can't handle bases below unary */
        if(b == 1)
                return c == '1'; /* special case */

        int loc = strchr(digits, c);
        return loc >= lowest && loc <= highest;
}

Есть ли преимущество использования версии schnaader, созданной для этого? (Похоже, это дает дополнительное преимущество, если не полагаться на то, что кодировка пользователя является ASCII, а не то, что это больше не имеет значения.)

Ответы [ 3 ]

4 голосов
/ 13 февраля 2011

Я бы предложил что-то вроде этого:

// input: char c
if (b <= 10) {
  if ((c >= '0') && (c < ('0' + b))) {
    // is digit
  }
} else if (b <= 36) {
  if ((c >= '0') && (c <= '9')) {
    // is digit
  } else if ((c >= 'A') && (c < 'A' + (b - 10))) {
    // is digit
  }
}

Это должно работать (не проверено) для базы 2..36, если вы используете 0 .. 9 и A .. Z.

Альтернативой может быть использование логической таблицы поиска, это самый быстрый способ проверки. Например, вы можете подготовить таблицы для баз 2..36, используя 256 * 35 = 8960 байт памяти, после чего проверка isdigit является простым чтением из памяти.

0 голосов
/ 13 февраля 2011

Преимущество isdigit состоит в том, что обычно это макрос, который расширяется во время компиляции.Существует также еще один isxdigit.

Если вы хотите сделать то же самое для вашего собственного соглашения о цифрах, вы можете воспользоваться функцией inline, которая была бы почти такой же хорошей:

inline
bool isdigit42(char c) {
  switch (c) {
    default: return false;
    case '0': return true;
    case '1': return true;
    .
    .
  }
}

Ваш компилятор будет лучше знать, какие случаи можно сократить, поскольку символы находятся в общем диапазоне значений.И в случае, если это вызывается с символом постоянной времени компиляции, это должно быть полностью оптимизировано.

0 голосов
/ 13 февраля 2011

если вы используете обычные основания (например, восьмеричные или шестнадцатеричные), вы можете использовать strtol() для преобразования и проверки состояния ошибки.если вы используете произвольные базы, например, базу 99, может не быть готового решения.

...