我知道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 - 不再重要了。)
答案 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
.. 9
和A
.. 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;
.
.
}
}
您的编译器会最好地了解哪些情况可以缩短,因为这些字符属于一个共同的值范围。如果使用编译时常量字符调用它,则应该完全优化掉。