The challenge
You will be given a string and your task will be to return a list of ints detailing the count of uppercase letters, lowercase, numbers and special characters, as follows.
Solve("*'&ABCDabcde12345") = [4,5,5,3].
--the order is: uppercase letters, lowercase, numbers and special characters.
The solution in C
Option 1:
void count_char_types (const char *string, unsigned counts[4])
{
char c;
counts[0] = counts[1] = counts[2] = counts[3] = 0;
while((c = *string++))
if(c >= 'A' && c <= 'Z') counts[0]++;
else if(c >= 'a' && c <= 'z') counts[1]++;
else if(c >= '0' && c <= '9') counts[2]++;
else counts[3]++;
}
Option 2:
#include <ctype.h>
void count_char_types (const char *string, unsigned counts[4])
{
counts[0] = counts[1] = counts[2] = counts[3] = 0;
for(const char* p = string; *p; p++){
if(isupper(*p)) counts[0]++;
else if(islower(*p)) counts[1]++;
else if(isdigit(*p)) counts[2]++;
else counts[3]++;
}
}
Option 3:
#include <string.h>
#include <ctype.h>
void count_char_types (const char *string, unsigned counts[4])
{
memset(counts, 0, 4 * sizeof(unsigned));
char c;
while((c = *string++)){
if (isupper(c)) ++counts[0];
else if (islower(c)) ++counts[1];
else if (isdigit(c)) ++counts[2];
else ++counts[3];
}
}
Test cases to validate our solution
#include <criterion/criterion.h>
extern void do_test (const char *string, const unsigned expected[4]);
#define ARRAY (const unsigned[4])
Test(tests_suite, sample_tests)
{
do_test("bgA5<1d-tOwUZTS8yQ", ARRAY {7, 6, 3, 2});
do_test("P*K4%>mQUDaG$h=cx2?.Czt7!Zn16p@5H", ARRAY {9, 9, 6, 9});
do_test("RYT'>s&gO-.CM9AKeH?,5317tWGpS<*x2ukXZD", ARRAY {15, 8, 6, 9});
do_test("$Cnl)Sr<7bBW-&qLHI!mY41ODe", ARRAY {10, 7, 3, 6});
do_test("@mw>0=QD-iAx!rp9TaG?o&M%l$34L.nbft", ARRAY {7, 13, 4, 10});
do_test("", ARRAY {0, 0, 0, 0});
}