让我们考虑一下任务的一半—从字符串化的基数n转换为无符号的long,其中n是2的幂(二进制为基数2,十六进制为基数16)。
如果您的输入是正常的,那么这项工作只不过是一个比较、一个子分形、一个移位和一个或每位数。如果你的输入不正常,那么,这就是它变得难看的地方,不是吗?做转换超快并不难。在任何情况下把它做好都是挑战。
所以假设你的输入是正常的,那么你转换的核心是:
unsigned long PowerOfTwoFromString(char *input, int shift)
{
unsigned long val = 0;
char upperLimit = 'a' + (1 << shift)
while (*input) {
char c = tolower(*input++);
unsigned long digit = (c > 'a' && c < upperLimit) ? c - 'a' + 10 : c - '0';
val = (val << shift) | digit;
}
return val;
}
#define UlongFromBinaryString(str) PowerOfTwoFromString(str, 1)
#define UlongFromHexString(str) PowerOfTwoFromString(str, 4)
你看这有多容易?它会在非正常输入时失败。你的大部分工作将是让你的输入保持理智,而不是表现。
现在,这个代码利用了两个移位的能力。它很容易扩展到基4,基8,基32等。它不会在两个基的非幂上工作。对于这些,你的数学必须改变。你得到
val = (val * base) + digit
这在概念上对这组操作是相同的。与基相乘等于移位。所以我可能会用一个完全通用的程序来代替。在清除输入的同时清除代码。在这一点上,strtoul可能是你最好的选择。这里有一个链接
a version
斯特图的。几乎所有的工作都是处理边缘条件——这会让你知道你的精力应该集中在哪里:正确的,有弹性的代码。与say的节省相比,使用位移位的节省将是最小的,而不是因为输入错误而崩溃。