试着用我粗鲁的英语解释:(
我的代码(假设所有输入都是正确的。避免防御性编程)
#include <stdio.h>
enum { SZ = 11 };
unsigned int htoi(const char *s);
int main()
{
char buff[SZ]; //Max 11 char: 0x XX XX XX XX '\0' (2 + 8 + 1)
while(fscanf(stdin, "%s", buff) != EOF)
printf("%X\n", htoi(buff) );
return 0;
}
unsigned int htoi(const char *s)
{
unsigned int i, r = 0;
for(i = (s[1] == 'x') ? 2 : 0; s[i] != '\0'; i++)
r = ( r << 4 ) + ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );
return r;
}
好的,首先,赋值 r = 0。然后,当我们开始 for-bucle 时,我们给索引变量 i 一个初始值。我们必须检查字符串是否为 0x 格式。我们只需要检查位置 1 就可以知道我们是否正在处理具有 0x 格式的输入字符串或没有它。
现在,我们有一个指向第一个正确字符的索引!对于每个迭代,我们向左移动 4 位。我们获得 4 个零。添加新十六进制数字的完美间隙!例子:
Input: 0xBE1234
Is s[1] == 'x' ? true then i = 2;
r = 0;
iter 1: r = 0x0; r = 0x0; r = 0xB;
iter 2: r = 0xB; r = 0xB0; r = 0xBE;
iter 3: r = 0xBE; r = 0xBE0; r = 0xBE1;
iter 4: r = 0xBE1; r = 0xBE10; r = 0xBE12;
iter 5: r = 0xBE12; r = 0xBE120; r = 0xBE123;
iter 6: r = 0xBE123; r = 0xBE1230; r = 0xBE1234
可能这有点复杂:
r = ( r << 4 ) + ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );
首先,我们替换 4 位,与每 16 位乘法相同,但效率更高。然后,我们查看是否有一个大于 '9' 的 ASCII 字符。如果这是真的,我们正在与 A、B、C、D、E、F 或 a、b、c、d、e、f 合作。请记住,我们假设我们有正确的输入。好的,现在看一下 ASCII 表:
A = 0100 0001 - a = 0110 0001
...
F = 0100 0110 - f = 0110 0110
但我们想要这样的东西:
A = 0000 1010 - a = 0000 1010
...
F = 0000 1111 - f = 0000 1111
我们怎么做?置换后,我们用掩码 s[i] & 0xF 清除 4 个最高有效位:
s[2] == 'B' == 0100 0010
s[2] & 0xF == 0000 0010
并添加 9 以适应整数值(仅在 { 'A'...'F', 'a' ... 'f' } 中的 s[i] 的情况下)
s[2] & 0xF + 0x9 = 0000 0010 + 0000 1001 = 0000 1011 (0xB)
最后,我们添加位移的 r 值并分配给 r。第二次迭代的执行顺序(s[3]):
r == 0xB, s[3] == 'E' == 0100 0101 (start iter 2)
(r << 4) == 0xB0, s[3] == 'E' == 0100 0101 (displacement r << 4 )
(r << 4) == 0xB0, (s[3] & 0xF + 0x9) == 0000 1110 == 0xE (clear most significant bits of s[3] and add 0x9)
r = (r << 4) + ( s[3] & 0xF + 0x9 ) == 0xBE == 1011 1110 (add all and assign to r)
如果我们有一个像 s[4] 这样的数字字符会发生什么?
s[4] == '1' == 0011 0001
s[4] & 0xF == 0000 0001
位移 r 四个位置,加 0(无),加上逻辑运算的结果 s[i] & 0xF 最后,赋值给 r。
r == 0xBE, s[4] == '1' == 0011 0001 (start iter 3)
(r << 4) == 0xBE0, s[4] == '1' == 0011 0001 (displacement r << 4 )
(r << 4) == 0xBE0, (s[4] & 0xF + 0x0) == 0000 0001 (clear most significant bits of s[4] and add 0)
r = (r << 4) + s[4] & 0xF == 0xBE1 == 1011 1110 0001 (add all and assign)
请记住,我们移动 4,因此我们不会对数字位进行网格划分,因为我们添加了具有四个零间隙的较低有效位。
PD:我保证提高我的英语以便更好地解释,对不起。