【问题标题】:best way to check if is digit in specific base in C检查C中特定基数是否为数字的最佳方法
【发布时间】:2011-02-13 00:55:31
【问题描述】:

我知道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 ——这不再重要了。)

【问题讨论】:

  • 99进制中允许哪些“数字”?
  • @Mark: 一些非常难以辨认的字符!!!
  • 允许的数字是那些您定义允许的...除了b&lt;=10b=16b=64,没有标准的允许数字集,您可以使用字母表在b=10b=36 之间进行推断,但过去是完全任意的
  • 基数永远小于 36。
  • “基数永远小于 36”——啊,那个老作业问题。

标签: c base digit


【解决方案1】:

我会建议这样的事情:

// 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,这应该适用于 base 2..36(未经测试)。

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

【讨论】:

  • 哦,我想你想要
  • 你为什么假设这些字母是连续的?您可能应该将其声明为限制。
  • @Dave:谢谢,这是一个复制和粘贴错误。已修复,谢谢。
  • @pax:好的,假设这里是 ASCII,但是我们在这里讨论 C 类型 char 时会有所不同吗?
  • 在 99.99% 的机器中,底层字符集是 ASCII。不幸的是(对我而言),我在 others 之一上做了一些工作 :-) z/OS USS 使用 EBCDIC 作为其底层字符集,ISO 特别声明只有 '0' 到 '9' 可以假定是连续的。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    如果您想为自己的数字约定做同样的事情,您可以使用几乎一样好的 inline 函数:

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

    您的编译器最清楚哪些情况可以缩短,因为字符在一个共同的值范围内。如果使用编译时常量字符调用它,则应该完全优化它。

    【讨论】:

    • 如果基数 b 可以介于 2 和 36 之间,你会得到像 case '7': return (b &gt; 7); 这样的行,这仍然可以,但我更愿意编写/检查/维护一些嵌套的 @987654327 @ 语句。
    猜你喜欢
    • 1970-01-01
    • 2020-11-21
    • 2010-12-20
    • 2016-07-02
    • 2015-11-03
    • 2012-07-10
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    相关资源
    最近更新 更多