My solution for this month’s Exercise took some terrible assumptions. First, that the strings are merely output and not stored. Second, that the strings are perfectly formed camelCase and snake_case. In this Lesson, I address the first concern.
To store the strings instead of outputting them directly, memory must be allocated. To determine the size, I need to know the original string size and then calculate the new string size based on the type of conversion. The issue here is whether to be spot-on accurate to just provide enough room for the worst case size of any given string.
It’s easier not to be spot-on accurate.
For the snake_case to camelCase conversion, the new string is always shorter than the original. Therefore, I can allocate storage based on the original string’s size.
For the camelCase to snake_case conversion, one character is added for each capital in the camelCase name. Here my cheat is to double the original string size, which more than handles a situation where every other character is capitalized (improbable but possible).
Here is my updated solution for this month’s Exercise. Error-checking on the malloc() function is omitted to keep the source code file short:
2023_08_12-Lesson.c
#include <stdio.h> #include <stdlib.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" }; char *v[count]; int x,c; char *n; for(x=0; x<count; x++ ) { n = variable[x]; /* initialize pointer n */ c = 0; /* initialize offset */ /* test for the underscore */ if( strchr(variable[x],'_') ) { /* name is in snake_case */ /* camelCase will be shorter, so just allocate the same storage */ v[x] = malloc( strlen(variable[x]) + 1 ); /* error checking goes here */ while( *n ) { if( *n=='_' ) { n++; *(v[x]+c) = toupper(*n); } else { *(v[x]+c) = *n; } n++; c++; } } else { /* name is in camelCase */ /* allocate storage for worst case */ v[x] = malloc( strlen(variable[x]) * 2 + 1 ); /* error checking goes here */ while( *n ) { if( isupper(*n) ) { *(v[x]+c) = '_'; c++; *(v[x]+c) = tolower(*n); } else { *(v[x]+c) = *n; } n++; c++; } } /* cap the string */ *(v[x]+c) = '\0'; } /* output the result */ for(x=0; x<count; x++ ) printf("%25s -> %s\n", variable[x], v[x] ); return(0); }
I’ve added several new variables to help build and store the new strings:
*v[]
is a char pointer array to store the new, converted strings.
c
is an int variable used to calculate offsets within a string. This variable is initialized to zero at each turn of the for loop: c = 0
For the snake_case to camelCase conversion, storage is allocated based on the size of the original string: v[x] = malloc( strlen(variable[x]) + 1 );
As opposed to being output (from my original solution), characters are stored instead, using variable c
as the offset within the freshly-allocated buffer: *(v[x]+c) = tolower(*n);
and *(v[x]+c) = *n;
Variable n
is incremented through the original string. Variable c
is incremented through the new string.
For the camelCase to snake_case conversion, I allocated memory based on double the size of the original string: v[x] = malloc( strlen(variable[x]) * 2 + 1 );
This is a bit of overkill, which I’ll address in next week’s Lesson.
As with the other conversion, variable n
plows through the original string while variable c
helps build the new string in the allocated storage.
After the strings are created, their capped with the null character as termination: *(v[x]+c) = '\0';
The output is the same as for the original solution, with the new strings are stored and not output directly. I suppose this approach is better, though more improvement is possible. I cover this step in next week’s Lesson.