From camelCase to snake_case – Solution

The challenge for this month’s Exercise is to convert a name from camelCase to snake_case and vice-versa. As usual, several approaches provide a possible solution. The directions were to output the results and not store them, so my solution is rather simple.

The first part of any solution is to identify the naming convention. Because snake_case uses the underscore, I use the strchr() function to scan for this character to determine whether it’s snake_case. If the character isn’t found, I can assume that camelCase is used instead. I recognize more assertive methods of determining the naming convention are possibly better, though for this Exercise the list of names provided is formatted consistently.

The strchr() function scans a named string for a specific character. If found, a pointer to the character’s offset is returned. Otherwise, NULL is returned:

if( strchr(variable[x],'_') )

The above statement is TRUE when the underscore is found in string variable[x]. This statement is the key to my solution, which uses an if-else structure within a for loop to process the sample names provided.

2023_08-Exercise.c

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

int main()
{
    const int count = 7;
    char *variable[] = {
        "readInputMeter",
        "cyclical_redundancy_check",
        "bumpyRide",
        "search_for_node",
        "string_convert",
        "divideByZeroError",
        "giveUpAndExplode"
    };
    int x;
    char *n;

    for(x=0; x<count; x++ )
    {
        printf("%25s -> ",variable[x]);
        n = variable[x];        /* initialize pointer n */

        /* test for the underscore */
        if( strchr(variable[x],'_') )
        {
            /* name is in snake_case */
            while( *n )
            {
                if( *n=='_' )
                {
                    n++;
                    /* test for overflow */
                    if( *n=='\0' ) break;
                    putchar( toupper(*n) );
                }
                else
                {
                    putchar(*n);
                }
                n++;
            }
        }
        else
        {
            /* name is in camelCase */
            while( *n )
            {
                if( isupper(*n) )
                {
                    putchar('_');
                    putchar( tolower(*n) );
                }
                else
                {
                    putchar(*n);
                }
                n++;
            }
        }
        putchar('\n');
    }

    return(0);
}

Pointer n scours each character in string variable[x]. For snake_case, *n is compared with the underscore: if( *n=='_' ) When an underscore is found, pointer n is incremented (over the underscore) to the next character: n++;

A test is performed after incrementing n just in case the underscore ends the string: if( *n=='\0' ) break; If true, the loop breaks. Otherwise, the uppercase version of the next character is output: putchar( toupper(*n) );

All other characters are handled in the else part of the decision, output directly: putchar(*n);

Pointer n is incremented after the nested if-else structure, continuing to churn through string variable[x].

Strings that aren’t identified as snake_case are camelCase. To process these strings, a while loop contains a nested if-else structure. The test here is whether a letter is in uppercase: if( isupper(*n) )

When found, an underscore is output, putchar('_');, then the current character is output in lowercase: putchar( tolower(*n) ); Otherwise, the character is output unmodified and n is incremented after the nested if-else construction.

The new strings are output immediately, which ends the string originally generated by a printf() statement:

printf("%25s -> ",variable[x]);

The %25s placeholder right-justifies the string, which makes the output appear symmetrical:

           readInputMeter -> read_input_meter
cyclical_redundancy_check -> cyclicalRedundancyCheck
                bumpyRide -> bumpy_ride
          search_for_node -> searchForNode
           string_convert -> stringConvert
        divideByZeroError -> divide_by_zero_error
         giveUpAndExplode -> give_up_and_explode

I hope your solution met with success. You get a special C For Dummies bonus point if you stored the strings before output. In fact, I cover this approach in an upcoming Lesson. Storing the strings adds more overhead, but it still works — and is probably a better solution as opposed to immediate output.

2 thoughts on “From camelCase to snake_case – Solution

  1. Do you know of a C library that parses source code, in particular identifying variable names?

    You know where I’m going with this . . . !

  2. I don’t. Though I’m sure there’s a parsing library somewhere, doing something akin to awk.

    Hmmm….

Leave a Reply