函数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
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
相关文章推荐
- 平衡二叉树的节点搜索函数——Ada应用实例之四
- Linux下的地址解析函数(res_*)的应用实例
- 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数--在实际中的应用
- php的IMAP的应用实例(实现收发邮件、删除邮件、附件下载等功能,解决中文乱码问题)
- JAVA线程的应用实例(运用2种中断线程方式,基于实现进度条为例)
- Android之——模拟实现检测心率变化的应用实例
- Android应用中实现选择本地文件与目录的实例分享
- UISearchDisplayController(iOS < 8.0)实例应用实现搜索功能和VC展示效果, 以及代理方法的介绍
- linux下C的fork函数应用实例
- abort系统函数应用实例
- Android应用中通过AIDL机制实现进程间的通讯实例
- iOS UITableView 简单应用中的两个实现函数
- 虚函数与纯虚函数的区别及H264Player应用实例
- PHP基于接口技术实现简单的多态应用完整实例
- JavaScript实现跨浏览器的添加及删除事件绑定函数实例
- JavaWeb应用实例:用servlet实现oracle 基本增删改查
- 应用:用函数实现两个变量值的交换
- 接口的多态使用; 接口应用实例:U盘、打印机可以使用共同的USB接口,插入到电脑上实现各自的功能。
- jquery滚动实现原理之一,自制滚动函数实例
- LinkedList链表实现队列应用的简单实例