对于连续的字符范围,您可以:
_Bool isbetween(int c, int start, int end){
return ((unsigned)c-start < (end-start));
}
要考虑大小写,请使用tolower() 和小写范围:
static inline int tolower(int c){
return c | ( ((unsigned)c-'A' < 26)<<5 );
}
//isbetween(tolower(x),'a','n');
对于非连续范围,您可能需要创建掩码。在这个例子中,我将检查元音(为简洁起见,因为只有 5 个,但可以使用 32 范围内的任何组合或 64 进行一些修改......
事实上,64 位平台上的 64 位掩码将消除对大小写处理的需要)。
static const unsigned vowel_mask = (1<<('a'-'a'))
|(1<<('e'-'a'))|(1<<('i'-'a'))|(1<<('o'-'a'))|(1<<('u'-'a'));
int isvowel(int c){ //checks if c is a,A,e,E,i,I,o,O,u,U
unsigned x = (c|32)-'a';
return ((x<32)<<x)&vowel_mask;
}
请注意,这些实现不包含分支;但是,使用无符号比较可能会阻止自动编译器矢量化(英特尔内在函数,没有无符号比较)......如果这是您的目标,您可以使用 2 &ed 比较来代替。根据字符的间隔距离,此方法可能适用于非 ascii 系统,也可能不适用。
海合会
isvowel:
or edi, 32 # tmp95,
xor eax, eax # tmp97
sub edi, 97 # x,
cmp edi, 31 # x,
setbe al #, tmp97
shlx eax, eax, edi # tmp99, tmp97, x
and eax, 1065233 # tmp96,
ret
叮当
isvowel: # @isvowel
or edi, 32
add edi, -97
mov eax, 32
xor ecx, ecx
cmp edi, eax
setb cl
shlx eax, ecx, edi
and eax, 1065233
ret
国际商会
isvowel:
xor eax, eax #15.26
or edi, 32 #14.23
add edi, -97 #14.27
cmp edi, 32 #15.26
setb al #15.26
shlx eax, eax, edi #15.23
and eax, 1065233 #15.26
ret #15.26
除了标准的 stackoverflow 许可,此代码已发布到公共领域