社区
英特尔边缘计算技术
帖子详情
Intel的朋友,能否推荐一个高效率的ANSI不区分大小写的检索函数?
danscort2000
2007-03-29 01:19:51
想在一个ANSI 字符串中检索一个子字符串
不区分大小写,也就是大写和小写看作一个字符
目前使用的方法是先拷贝,然后全部转换到小写,再调用strstr来进行检索
感觉效率太低,
有没有高手能提供一个高效率的函数?或者思路也行
不要使用CString string等,全部采用 char 指针进行操作,非常感谢
...全文
385
22
打赏
收藏
Intel的朋友,能否推荐一个高效率的ANSI不区分大小写的检索函数?
想在一个ANSI 字符串中检索一个子字符串 不区分大小写,也就是大写和小写看作一个字符 目前使用的方法是先拷贝,然后全部转换到小写,再调用strstr来进行检索 感觉效率太低, 有没有高手能提供一个高效率的函数?或者思路也行 不要使用CString string等,全部采用 char 指针进行操作,非常感谢
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
22 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
flyingdog
2007-04-05
打赏
举报
回复
既然你用上了汇编,那就有其他办法提高速度了。
比如字符比较没必要一个一个比。每个字符是8位的,对于搜索字符是4个字符的情况。正好32位。可以进行32位的同时比较。
至于搜索字符不是正好4个字符的情况,也可以想办法。
flyingdog
2007-04-05
打赏
举报
回复
在程序运行时进行大小写转换虽然剩了复制的时间。但是怎么多条件判断会影响cpu的执行性能的。
还是试试使用查表转换的方法。
flyingdog
2007-04-05
打赏
举报
回复
后缀树和后缀数组就算了,实现复杂,常数大。
针对这个数据规模,其他算法可能没什么用。但是KMP的常数应该不大。
贴一个KMP模板。只是模板,不针对这个程序。
#define MAXLEN 1000
int T[MAXLEN];
void kmp_table(char *P){
int i=0;
int j=-1;
char c='\0';
T[0]=j;
while (P[i]!='\0'){
if (P[i]==c){
T[i+1]=j+1;
++j;
++i;
}
else if (j>0){
j=T[j];
}
else {
T[i+1]=0;
++i;
j=0;
}
c = P[j];
}
}
int kmp_search(char *P, char *S){
kmp_table(P);
int m = 0;
int i = 0;
while (S[m+i]!='\0'&&P[i]!='\0') {
if (S[m+i]==P[i]){
++i;
}
else {
m+=i-T[i];
if (i>0)i=T[i];
}
}
if (P[i]=='\0'){
return m;
}
else {
return m+i;
}
}
flyingdog
2007-04-05
打赏
举报
回复
为什么一定要偶数?
比如3个字符的时候,把最高位与成0不是就行了?
flyingdog
2007-04-05
打赏
举报
回复
你前面不是说“而检索子串一般是2到8个字符”??
怎么现在又变成“可能超过16个字符”??
那就先做一个判断,对于短的使用汇编优化掉,对于长的使用KMP。
danscort2000
2007-04-05
打赏
举报
回复
对于是4个字符或者8个字符,这个确实可以优化
问题是这个长度是用户指定的,可能超过16个字符,不一定是偶数
如果要针对性优化,恐怕前面的判断部分和后续的分支判断就需要大量的CPU时间了
所以暂时不用
今天修改了函数,对IO又进行了优化,首先判断长度,用FOR代替了WHILE,这样里面的判断又少了很多
danscort2000
2007-04-05
打赏
举报
回复
现在已经找到方法了,不用ASM汇编,也不用KMP,
目前的逻辑是:
首先计算两个长度
然后对子串全部大写或者小写
用两个FOR代替WHILE[这里可以根据子串的长度优化掉一部分检索]
这样的函数速度比原来汇编的那个还快
danscort2000
2007-04-05
打赏
举报
回复
你前面不是说“而检索子串一般是2到8个字符”??
怎么现在又变成“可能超过16个字符”??
那就先做一个判断,对于短的使用汇编优化掉,对于长的使用KMP。
这个已经说明是一般了,因为这是用户决定的检索关键字
并没有规定最长长度,根据统计资料,一般就是2-8个字符
danscort2000
2007-04-04
打赏
举报
回复
KMP检索函数有了
但是我看了实现
太慢了,这个对全文检索可能意义不错,但是用在我这个场合比我的还慢,
现在用这个实现,如何?
char *AsmStrStrI(char *p1, char *p2) // p1=source
{
char c=0;
while(*p1)
{
__asm
{
mov ecx, p1
mov edx, p2
StartLoop:
mov al, [ecx]
mov ah, [edx]
inc ecx
inc edx
cmp al,0
je EndLoop
cmp ah,0
je EndLoop
cmp al, 'a'
jb Next
cmp al, 'z'
ja Next
and al, 11011111b
Next:
cmp ah, 'a'
jb Compare
cmp ah, 'z'
ja Compare
and ah, 11011111b
Compare:
cmp al, ah
je StartLoop
EndLoop:
mov c, ah
}
if(c==0)
{
return p1;
}
p1++;
}
return NULL;
}
赖勇浩
2007-04-04
打赏
举报
回复
这个肯定是慢了,楼主先实现一个KMP算法吧~
还有一些比KMP更快的算法,你可以找一下相关的ACM论文。
danscort2000
2007-04-04
打赏
举报
回复
现在的优化是,
我在调用前,首先对子串UPCASE
然后传入这个函数
因此没有最前面的那个while循环
danscort2000
2007-04-04
打赏
举报
回复
上面有个错误,加了const ,应该是 char *
danscort2000
2007-04-04
打赏
举报
回复
char * AnsiNocaseStrstr(const char *src,const char *sub)
{
if(*sub==0) return NULL;
if (*src == 0)
{
if (*sub) return NULL;
return src;
}
char c;
size_t i=0;
while(sub[i])
{
if(sub[i] >= 'A' && sub[i] <= 'Z') sub[i] += 0x20;
i++;
}
while (*src)
{
i=0;
while (1)
{
if(sub[i] == 0) return src;
if(src[i]==0) return NULL;
c=src[i];
if(c >= 'A' && c <= 'Z') c += 0x20;
if( sub[i] != c) break;
i++;
}
src++;
}
return NULL;
}
IntelSupport
2007-04-04
打赏
举报
回复
能不能举个一般性能的ANSI不区分大小写的检索函数先
danscort2000
2007-04-03
打赏
举报
回复
哎,看来是没有办法了
等等看,有没有更好的方法
flyingdog
2007-04-01
打赏
举报
回复
的确有PCMPEQB指令,可以进行8个或者16个的同时比较,但是这个并不适合你的要求。因为比较结果是写入mask位,而不是更改flag值。而且无法解决大小写转换问题。具体的指令用法你可以查相应文档。
danscort2000
2007-03-31
打赏
举报
回复
现在是自己写代码了,去掉了内存拷贝转换导致的时间,
大小写直接比较,
由于子串一般都很小,比如2个字符到4个字符,很复杂的算法我不知道是否反而导致低效率
明天继续进行优化,
我想知道是否可以利用MMX啊?
flyingdog
2007-03-31
打赏
举报
回复
如果真要非常注重高效,还是自己写代码比较好。
你使用KMP算法试试,复杂度是O(n+m)。
至于大小写问题,我想到一个方法,不需要先拷贝再转小写,但是不知道实际效果如何,你可以试试。也欢迎大家讨论。
比如对于A和a来说,搜索子串先转成小写。定义一个长度为256的数组T[256]
T['a']='a'
T['A']='a'
T[str[i]]就能在比较时进行转换。
danscort2000
2007-03-30
打赏
举报
回复
只要找到一个就可以了
不需要全部
danscort2000
2007-03-30
打赏
举报
回复
谢谢,不过不想用四string类
因为我有上万个字符串,每个串一般是16个到128个字符
而检索子串一般是2到8个字符
我希望是ANSI检索函数,事实上那个strstr是我自己重新写过的
主要想避免内存分配与拷贝,这个过程太耗费时间,
想将大小写检索都放在一个函数中
其实INTEL 可以开发一个高效率而简短的ANSI检索函数,这个经常要用到的
加载更多回复(2)
ANSI
C文件管理.ppt
“
ANSI
C 标准文件 I/O 操作”涉及到一组库
函数
,这些
函数
允许程序员打开、关闭、读取、写入和控制文件。常见的
函数
包括 `fopen()` 用于打开文件,`fclose()` 用于关闭文件,`fread()` 和 `fwrite()` 用于读写数据,...
VC++6.0核心编程源码.rar
建立这样
一个
列表时存在的问题是,你可以调用
一个
Windows
函数
,但是该
函数
能够在内部调用另
一个
函数
,而这另
一个
函数
又可以调用另
一个
函数
,如此类推。由于各种不同的原因,这些
函数
中的任何
一个
函数
都可能运行失败...
数据库技术及应用:第4章关系数据库语言SQL.ppt
1. 不
区分
大小写
,但为了代码可读性,通常关键词大写,表名和列名小写。 2. 语句可以跨行书写,但关键字不应断行。 3. 数据项间使用逗号分隔,字符串需用单引号包围。 SQL中的主要查询类型包括: - 基本查询:简单...
关系数据库语言SQL知识介绍.pptx
- **
大小写
不敏感**:SQL语句的关键字和标识符通常不
区分
大小写
。 - **一行或多行**:一条语句可以跨越多行书写,但关键字必须保持完整,不可分割。 - **逗号分隔**:在列出多个数据项时,用逗号作为分隔符。 - **单...
4汽车服务企业信息化管理基础4关系数据库语言SQL.pptx
- 不
区分
大小写
,但为了可读性,通常关键词大写,对象名小写。 - 语句可一行或多行书写,但关键字不应断行。 - 数据项之间用逗号分隔,字符串需用单引号包围。 在汽车服务企业中,SQL可用于管理客户信息、车辆维修...
英特尔边缘计算技术
568
社区成员
7,024
社区内容
发帖
与我相关
我的任务
英特尔边缘计算技术
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
复制链接
扫一扫
分享
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章