检查C中特定基数是否为数字的最佳方法

时间:2011-02-13 00:55:31

标签: c base digit

我知道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 个答案:

答案 0 :(得分:4)

我建议这样的事情:

// 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
  }
}

如果你使用的是0 .. 9A .. Z,这应该适用于基础2..36(未经测试)。

另一种方法是使用布尔查找表,这是最快的检查方式。例如,您可以为基数2..36准备表,使用256 * 35 = 8960字节的内存,此后isdigit检查是一个简单的内存读取。

答案 1 :(得分:0)

如果您使用常规基(例如八进制或十六进制),则可以使用strtol()进行转换并检查错误情况。如果您使用任意碱基,例如基础99可能没有开箱即用的解决方案。

答案 2 :(得分:0)

isdigit的优点是它通常是一个在编译时扩展的宏。还有一个isxdigit

如果你想为你自己的数字惯例做同样的事情,你可以选择一个几乎同样好的inline函数:

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

您的编译器会最好地了解哪些情况可以缩短,因为这些字符属于一个共同的值范围。如果使用编译时常量字符调用它,则应该完全优化掉。