试着用我粗鲁的英语解释:(
我的代码(假设所有输入都是正确的。避免防御性编程)
#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:我保证提高我的英语以便更好地解释,对不起。