您的位置:首页 > 其它

函数strspn的实现——Ada应用实例之八

2009-12-10 17:52 323 查看
函数strspn的实现——Ada应用实例之八

strspn是C语言中的一个函数,它的功能是计算字符串s1中第一个在字符串s2中没有出现过的字符的位置。一帖子讨论了strspn的如下实现算法(本文修改了参数名称):
int strspn (unsigned char *s1, unsigned char *s2)
{
unsigned char map[32];
int count;

for (count = 0; count < 32; count++)
map[count] = 0;
while (*s2)
{
map[*s2 >> 3] |= (1 << (*s2 & 7));
s2++;
}

count = 0;
if (*s1)
{
while (map[*s1 >> 3] & (1 << (*s1 & 7)))
{
count++;
s1++;
}

return(count);
}

return(0);
}

该算法的巧妙之处是map的设计和使用。map是一个由32个字节组成的数组,它相当于有256个二进制位,每位映射到一个ASCII码。每个ASCII码(设为c)有8位,把它分为2部分,低3位构成下标j(通过c & 7得到),高5位构成下标i(通过c>>3得到),下标j就是在map[i]中的第j位。
例如,对于字符‘1’,其ASCII码是0x31,>>3得6,&7得1,也就是它在map[6]的第1位,通过1 <<1得1,然后与map[6]相与。
假如使用Ada来实现strspn,有如下代码:
package body strspn is
type ascii_map_type is array (Character'Range) of Boolean;
pragma Pack (ascii_map_type); --用紧凑方式为ascii_map_type分配内存,这样只需256BIT

function strspn (s1 : in String; s2 : in String) return Integer is
position : Integer;
map : ascii_map_type;
begin
for i in map'Range loop --初始化
map (i) := False;
end loop;

for i in s2'Range loop --以s2中每个字符为下标在map中置True
map (s2 (i)) := True;
end loop;

for i in s1'Range loop
if map (s1 (i)) = False then --以s1中每个字符为下标判断它是否在s2中出现过
position := i;
exit;
end if;
end loop;

return position;
end strspn;
end strspn;

Ada字符串中字符的位置默认从1开始计数,而C是从0开始。因此上述程序的结果比C程序的结果多1。
用Ada编写的函数strspn比C程序易于理解,Ada编译生成的目标码可与C程序媲美。其中对map的置值或判断也是通过>>3和&7实现的。以下是以s2中每个字符为下标在map中置True的目标码:
.text:00401664 mov ebx, esi
.text:00401666 mov eax, [ebp+var_38]
.text:00401669 mov edi, 1
.text:0040166E mov esi, [ebp+var_44]
.text:00401671 mov [ebp+var_4C], eax
.text:00401674 jmp short loc_40167E
.text:00401676 loc_401676: ; CODE XREF: sub_401600+97j
.text:00401676 mov ecx, [ebp+var_4C]
.text:00401679 inc ebx
.text:0040167A inc ecx
.text:0040167B mov [ebp+var_4C], ecx
.text:0040167E loc_40167E: ; CODE XREF: sub_401600+74j
.text:0040167E mov edx, [ebp+var_4C]
.text:00401681 xor ecx, ecx
.text:00401683 mov cl, [edx]
.text:00401685 mov edx, edi
.text:00401687 mov eax, ecx
.text:00401689 and ecx, 7
.text:0040168C shr eax, 3
.text:0040168F shl edx, cl
.text:00401691 or [ebp+eax+var_30], dl
.text:00401695 cmp ebx, esi
.text:00401697 jnz short loc_401676
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: