Since all these ctype.h functions have the same format int func (int)
, you can take advantage of that to create a look-up table corresponding to all checks that need to be done. The advantage of a look-up table is that it's much easier to maintain than a fairly unreadable chain of &&
.
First create a function typedef identical to the ctype functions: typedef int ctype_func_t (int);
Then make a struct to be used in the look-up table. Store string index, the true or false condition of the result, and the function itself:
typedef struct
{
size_t index;
bool cond;
ctype_func_t* check_func;
} check_t;
A look-up table can then be created as:
const check_t fmt_check [] =
{
{0, true, isupper },
{1, false, isalpha },
{2, false, isalpha },
{1, false, isdigit },
{2, false, isdigit },
{3, true, isdigit },
{4, true, isdigit },
{5, true, isdigit },
{6, true, isalpha },
{7, true, isalpha },
};
The order isn't important, add or remove format requirements as you please. The complete function for this would look like:
int ispwcorrect (const char pw[8])
{
typedef int ctype_func_t (int);
typedef struct
{
size_t index;
bool cond;
ctype_func_t* check_func;
} check_t;
const check_t fmt_check [] =
{
{0, true, isupper },
{1, false, isalpha },
{2, false, isalpha },
{1, false, isdigit },
{2, false, isdigit },
{3, true, isdigit },
{4, true, isdigit },
{5, true, isdigit },
{6, true, isalpha },
{7, true, isalpha },
};
for(size_t i=0; i<sizeof fmt_check/sizeof *fmt_check; i++)
{
unsigned char ch = pw[ fmt_check[i].index ];
if((bool)fmt_check[i].check_func(ch) != fmt_check[i].cond)
{
return false;
}
}
return true;
}
This should be fairly self-explanatory, it calls ctype functions through a function pointer in a loop with a specific string index character as parameter. Then checks against a true/false condition. The check stops as soon as there is a mismatch.
The cast to bool
after calling each ctype function is necessary, since they return zero or non-negative int
. So comparing a bool
against such a non-zero int
won't work, since == will promote the bool
parameter to an int
.
This should vastly outperform regex, but will be slightly slower than the raw if-else.
Unrelated to your question, you also have a severe bug here: char pass[8];
. There is no room for the null terminator, so you can't store "L$$222ee"
inside pass
.