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

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

 

strspnC语言中的一个函数,它的功能是计算字符串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>>36&71,也就是它在map[6]的第1位,通过1 <<11,然后与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编写的函数strspnC程序易于理解,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值