Ответ 1
const char invalidChars[] = "edpq";
while (strchr(invalidChars, tolower(option)) != 0) {
...
}
В настоящее время я могу запустить свою программу, но мой код состоит из большого количества повторений, которые выглядят примерно так:
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)
(но интерфейс С++ установлен очень минимален).
Однако для небольшого количества сравнений ваш метод, вероятно, быстрее.
Быстрый тест кандидата без ветвления.
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("%X\n", CaseMaskBits);
for (ch = 0; ch < 256; ch++){
int t; // temp var for TestEQ4
while (TestEq4(ch, t, "ELPQ")) {
printf("%d %c\n", 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 %c\n", ch, ch);
Если option/cType
имеет <= 8 бит значения, для скорости, используйте поиск таблицы. @Dieter Lücking
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);
}