如何缩短多重&&&条件

How to shorten multiple && condition

本文关键字:条件 何缩短      更新时间:2023-10-16

目前我可以运行我的程序,但我的代码由很多重复组成,看起来像:

while(option != 'E' && option != 'D' && option != 'P' && option != 'Q' &&
      option != 'e' && option != 'd' && option != 'p' && option != 'q') {
  // Some code here
}

或:

while(cType != 'S' && cType != 'L' && cType != 'O' && cType != 'Q' &&
      cType != 's' && cType != 'l' && cType != 'o' && cType != 'q') {
  // Some code here
}

缩短以上代码的最快方法是什么?

const char invalidChars[] = "edpq";
while (strchr(invalidChars, tolower(option)) != 0) {
    ...
}

您可以初始化一个包含您想要匹配的字符的字符串,然后使用find,如果没有找到匹配,则返回npos:

string match = "SLOQsloq";
while (match.find(cType) == string::npos)
  ...

使用std::tolower可以消除一半的条件

while(std::tolower(option) != 'e' && std::tolower(option) != 'd' && std::tolower(option) != 'p' && std::tolower(option) != 'q')

您也可以使用std::string及其find成员函数,如:

std::string options = "edpq";
//...
while (options.find(std::tolower(option)) == std::string::npos)

可以通过使用std::set并检查集合是否包含(或不包含)我们正在比较的变量来简化逻辑并使内容更易于阅读:

std::set<char> someChars { 'a', 'b', 'c' };
if(someChars.find(myChar) != someChars.end()) {
    // myChar is either 'a', 'b', or 'c'
}

在大多数其他语言中,这个条件会写得更干净,比如someChars.contains(myChar)(但是c++的set接口非常小)。

但是,对于少量的比较,您的方法可能更快。

一个没有分支的候选快速测试。

1)无大小写。
2)形成4个差的乘积。
3) 1与0比较

只接受字母。
最多4个(sizeof int/sizeof char)字母。
大小写相差相同位。(适用于ASCII和EBCDIC)

#define CaseMaskBits ((unsigned char)~('A'^'a'))
#define Product4(ch, s) ((ch-s[0]) * (ch-s[1]) * (ch-s[2]) * (ch-s[3]))
#define TestEq4(ch, t, s)  (t=ch&CaseMaskBits, !Product4(t, s))
int main(void) {
  int ch;
  printf("%Xn", CaseMaskBits);
  for (ch = 0; ch < 256; ch++){
    int t;  // temp var for TestEQ4
    while (TestEq4(ch, t, "ELPQ")) {
      printf("%d %cn", ch, ch);
      break;
    }
  }
  return 0;
}
280           while (TestEq4(ch, t, "ELPQ")) {
00402560:   mov %ebx,%eax
00402562:   and $0xdf,%eax
00402567:   lea -0x4c(%eax),%edx
0040256a:   lea -0x45(%eax),%ecx
0040256d:   imul %edx,%ecx
00402570:   lea -0x50(%eax),%edx
00402573:   sub $0x51,%eax
00402576:   imul %ecx,%edx
00402579:   imul %edx,%eax
0040257c:   test %eax,%eax
0040257e:   jne 0x402555 <main+37>
281             printf("%d %cn", ch, ch);

如果option/cType有<= 8位的重要性,为了速度,使用表查找。@Dieter高年级队

unsigned char Table[UCHAR_MAX + 1] = {
  fill per needs };
#define Table_OptionMask 1
#define Table_cTypeMask 2
#define Table_nextMask 4
while (!(Table[(unsigned char)option] & Table_OptionMask)) ...
while (!(Table[(unsigned char)cType] & Table_cTypeMask)) ...

为了简化代码维护,在代码启动时调用Table_Setup()填充表。

static void Table_SetInsensitive(unsigned char *Table, unsigned mask, cnst char *src) {
  while (*src) {
    Table[toupper((unsigned char) *src)] |= mask;
    Table[tolower((unsigned char) *src)] |= mask;
    src++;  
  }
}
void Table_Setup(void) {
  memset(Table, 0, sizeof Table);
  Table_SetInsensitive(Table, Table_OptionMask, "EDPQ");
  Table_SetInsensitive(Table, Table_cTypeMask, "SLOQ");
  Table_SetInsensitive(Table, Table_cTypeMask, tbd);
}