how to find out what case style a string is (pascal, snake, kebab, camel)

581 views Asked by At

I want to write a program that outputs whether a string is styled in pascal case, camel case, snake case, kebab case, or none of them. in the first line, we should take integer n from input. then, in the next n lines, we should take an integer k and then a string with no space in each line. k is the size of the string. here's an example of how each of these case styles look like:

pascal case => HelloWorld
camel case => helloWorld
snake case => hello_world
kebab case => hello-world

e.g: input :

3
11 masterShifu
12 master_shifu
12 MASTER_SHIFU

output:

camel case
snake case
undefined case style

my problem with this program is that I don't know how to find the first letter of each word since there's no space between two different words. this is what i've written so far:

#include <stdio.h>
#include <ctype.h>

int
main()
{
    int n;

    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int k;

        scanf("%d ", &k);
        char word[k];

        gets(word[k]);
        int count = 0;

        if (isupper(word[0]) == 1) {
            for (int i = 1; i < n; i++) {
                if (isupper(word[i]) == 1) {
                    count++;
                }
            }
            if (count == k)
                printf("Undefined Case Style\n");
            else
                printf("PascalCase\n");
        }
        else {
            int c = 0,
                s = 0,
                count = 0;

            for (int i = 0; i < n; i++) {
                if (word[i] == '-') {
                    c++;
                    printf("kebab-case\n");
                    break;
                }
                else if (word[i] == '_')    // snake case
                {
                    s++;
                    printf("snake_case\n");
                    break;
                }
                else if (isupper(word[i]) == 1) // camel case
                {
                    count++;
                    printf("camelCase\n");
                    break;
                }

            }
            if (c == 0 && s == 0)
                printf("Undefined Case Style\n");
        }
    }
    return 0;
}
1

There are 1 answers

0
Allan Wind On

I suggest you iterate through the input string s then given current character *s and what case found you have found determine if the *s is a valid and what the new found is or you can terminate processing.

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>

enum str_case {
    CAMEL,
    KEBAB,
    PASCAL,
    SNAKE,
    UNDEFINED,
};

enum str_case str2str_case(const char *s) {
    enum str_case found = isupper(*s++) ? PASCAL : UNDEFINED;
    for(; *s; s++) {
        if(*s == '-') {
            if(found == KEBAB)
                continue;
            if(found == UNDEFINED) {
                found = KEBAB;
                continue;
            }
            return UNDEFINED;
        }
        if(*s == '_') {
            if(found == SNAKE)
                continue;
            if(found == UNDEFINED) {
                found = SNAKE;
                continue;
            }
            return UNDEFINED;
        }
        if(isupper(*s)) {
            if(found == CAMEL || found == PASCAL)
                continue;
            if(found == UNDEFINED) {
                found = CAMEL;
                continue;
            }
            return UNDEFINED;
        }
        if(!islower(*s))
            return UNDEFINED;
    }
    return found;
}

int main(void) {
    struct test {
        char *input;
        enum str_case expected;
    } tests[] = {
        {"helloWorld", CAMEL},
        {"hello-world", KEBAB},
        {"HelloWorld", PASCAL},
        {"hello_world", SNAKE},
        {"", UNDEFINED},
        {"!", UNDEFINED},
        {"A-b", UNDEFINED},
        {"a_b-c", UNDEFINED},
    };
    for(struct test *t = tests; t < tests + sizeof tests / sizeof *tests; t++) {
        enum str_case got = str2str_case(t->input);
        if(t->expected != got) {
            printf("fail: %s: expected %d but got %d\n", t->input, t->expected, got);
            continue;
        }
        printf("ok\n");
    }
}

and here is the output:

ok
ok
ok
ok
ok
ok
ok
ok

I would then refactor the code with the macro:

#define CHECK(char_predicate, state_predicate, new_state) \
    if((char_predicate)) {\
        if((state_predicate))\
            continue;\
        if(found == UNDEFINED) {\
            found = (new_state);\
            continue;\
        }\
        return UNDEFINED;\
    }

and the function becomes simply:

enum str_case str2str_case(const char *s) {
    enum str_case found = isupper(*s++) ? PASCAL : UNDEFINED;
    for(; *s; s++) {
        CHECK(*s == '-', found == KEBAB, KEBAB);
        CHECK(*s == '_', found == SNAKE, SNAKE);
        CHECK(isupper(*s), found == CAMEL || found == PASCAL, CAMEL);
        if(!islower(*s))
            return UNDEFINED;
    }
    return found;
}

Other than fgets() instead of gets() you didn't seem to have issues with parsing the input format, and generating the expected output format so leaving that as an exercise to reader.