Search code examples
ccharc-stringsfunction-definitiontolower

How to build toLower for string correctly


I'm trying to perform case insensitive strcmp on full name string. I have a function to convert C-style strings to lowercase.

    char* toLowerCase(char* string){
    
        char *s = string;
        unsigned long int s_len = strlen(s);
        char sToLower[s_len];
    
        for (int i = 0; i < s_len; i++)
            sToLower[i] = tolower(s[i]);
        sToLower[s_len] = 0;
    
        s = sToLower;
        return s;
    }

but strcpy and strcat doesn't work. how to solve it?

        char fullName[1024] = "";
        strcpy(fullName, toLowerCase(p->data.firstName));
        strcat(fullName, toLowerCase(p->data.lastName));

Solution

  • The function toLowerCase is incorrect because it returns a pointer to a local array that will not be alive after exiting the function. So using this pointer to access memory will invoke undefined behavior.

    char* toLowerCase(char* string){
    //...
    char sToLower[s_len];
    //...
    s = sToLower;
    return s;
    }
    

    Moreover the size of the local array is specified incorrectly

    char sToLower[s_len];
    

    you need declare it at least like

    char sToLower[s_len + 1];
    

    to reserve memory for the terminating zero character '\0'.

    Either you need to change the source string in place (but in this case the function may not be used with string literals) or you need within the function to create dynamically a new array and store there the source string converted to lower case.

    For example

    char* toLowerCase( const char* s )
    {
        char *sToLower = malloc( strlen( s ) + 1 );
    
        if ( sToLower != NULL )
        {
            char *p = sToLower;
            while ( ( *p++ = tolower( ( unsigned char )*s++ ) ) != '\0' );
        }
    
        return sToLower;
    }
    

    You will need to free the allocated memory in the function for the returned string when the string will not be required any more.

    Or the function can be declared with two parameters that specify the source array and the destination array like

    char* toLowerCase( char *dsn, const char* src );
    

    That is the user of the function must supply the destination array that will store the source string converted to lower case.