Как упростить проверку на все арабские цифры в произвольной строке?
#include <iostream>
using namespace std;
void check_rule(char* MyLine)
{
if ((strchr(MyLine, '1') && (strchr(MyLine, '2') && (strchr(MyLine, '3') && (strchr(MyLine, '4') && (strchr(MyLine, '5') && (strchr(MyLine, '6')
&& (strchr(MyLine, '7') && (strchr(MyLine, '8') && (strchr(MyLine, '9') && (strchr(MyLine, '0'))))))))))))
{
cout << "В строке есть все арабские цифры" << endl;
}
else
{
cout << "В строке не все арабские цифры" << endl;
}
}
int main()
{
setlocale(LC_ALL, "Russian");
//char TestLine[100] = "sajsafhasfsafasufa213453456345789056735421dssa \\|\?dasd123";
char MyLine[100];
cout << "Введите символы для проверки" << endl;
gets_s(MyLine);
cout << "Введенные символы для проверки " << MyLine << endl;
check_rule(MyLine);
return 0;
}
Ответы (3 шт):
Ну, например, так:
bool check_rule(const char* MyLine)
{
for(char c = '0'; c <= '9'; ++c)
if (strchr(MyLine,c) == nullptr) return false;
return true;
}
Но, возможно, лучше сканировать всю строку и проверять наличие цифр - все равно strchr такое сканирование выполняет, так зачем терять уже просмотренные результаты? типа
bool check_rule(const char* MyLine)
{
bool dig[10] = { false };
for(const char *c = MyLine; *c; ++c)
if (isdigit(*c)) dig[*c-'0'] = true;
bool ok = true;
for(int i = 0; i < 10; ++i) ok &= dig[i];
return ok;
}
Если о строках что-то известно дополнительно - что встречается чаще, строки с полным набором или нет, очень длинные или нет etc - можно подумать над другими вариантами, или поэкспериментировать, что будет быстрее.
P.S. Я просто возвращаю из функции значение в соответствии с принципом, что каждая функция должна заниматься одним делом. Эта - проверяет выполнение правила, выводить строки на экран - дело другой функции.
Update
Для непонятливых...
void check_rule(const char* MyLine)
{
for(char c = '0'; c <= '9'; ++c)
if (strchr(MyLine,c) == nullptr)
{
cout << "В строке не все арабские цифры" << endl;
return;
}
cout << "В строке все арабские цифры" << endl;
}
void check_rule(const char* MyLine)
{
bool dig[10] = { false };
for(const char *c = MyLine; *c; ++c)
if (isdigit(*c)) dig[*c-'0'] = true;
bool ok = true;
for(int i = 0; i < 10; ++i) ok &= dig[i];
if (ok) cout << "В строке все арабские цифры" << endl;
else cout << "В строке не все арабские цифры" << endl;
}
Можно сделать сопоставление значения цифры и булевого флажка, встретилась она или нет. Такой подход позволит обработать входную строку за один проход.
#include <array>
#include <cstddef>
void check_rule(char const * psz_text)
{
::std::array<bool, 10> map{};
::std::size_t count{};
for (;;)
{
if ('\0' == *psz_text)
{
::std::cout << "В строке не все арабские цифры" << ::std::endl;
break;
}
if (('0' <= *psz_text) && (*psz_text <= '9'))
{
auto & entry{map[*psz_text - '0']};
if (not entry)
{
++count;
if (map.size() == count)
{
::std::cout << "В строке есть все арабские цифры" << ::std::endl;
break;
}
entry = true;
}
}
++psz_text;
continue;
}
}
Как вариант
void check_rule(char const* myLine)
{
// Флаг, каждый бит которого отражает встречающуюся цифру в строке
unsigned short flag = 0;
//макрос для экономии места
//выполняет побитовое ИЛИ с флагом, где каждый бит отражает цифру
//и проверяет, равен ли флаг значению 1023 (1111111111 в бинарном виде),
//что свидетельствует о том, что все цифры встречаются
#define CHECK(b) flag |= b; \
if(flag == 1023) { \
std::cout << "В строке есть все арабские цифры" << std::endl; \
return; \
}
while(*myLine) {
switch (*myLine) {
case '0': CHECK(1) break;
case '1': CHECK(2) break;
case '2': CHECK(4) break;
case '3': CHECK(8) break;
case '4': CHECK(16) break;
case '5': CHECK(32) break;
case '6': CHECK(64) break;
case '7': CHECK(128) break;
case '8': CHECK(256) break;
case '9': CHECK(512)
}
++myLine;
}
std::cout << "В строке не все арабские цифры " << std::endl;
}