Search code examples
cstringstring-concatenation

Concatenating two strings with strncat


I would like to concatenate two strings, adding a new random character, using strncat() so basically I'm doing this:

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

#define CHARACTER_RANGE 25
#define INITIAL_CHARACTER 65

int main(){
    char male[32] = "A", female[32] = "B", new_letter[1], new_name[32];
    srand(time(NULL));

    strcpy(new_name, male);
    strncat(new_name, female, sizeof(new_name) - strlen(new_name) - 1);

    new_letter[0]= (rand() % CHARACTER_RANGE) + INITIAL_CHARACTER;

    strncat(new_name, new_letter, sizeof(new_name) - strlen(new_name) - 1);

    printf("New string is %s!\n", new_name);

    return 0;
}

In case of new letter is F expected result should be:

New string is ABF!

Instead, the result is:

New string is ABFAB!

I can't figure out why this happens.


Solution

  • The second call to strncat is incorrect:

    strncat(new_name, new_letter, sizeof(new_name) - strlen(new_name) - 1);
    

    new_letter is not a proper C string, as it does not have a null terminator, nor is there any space to store it after the letter. If sizeof(new_name) - strlen(new_name) - 1 is greater than 1, the behavior is undefined.

    Here is a corrected version:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    #define CHARACTER_RANGE 25
    #define INITIAL_CHARACTER 65
    
    int main() {
        char male[32] = "A", female[32] = "B", new_letter[2], new_name[32];
    
        srand(time(NULL));
    
        strcpy(new_name, male);
        strncat(new_name, female, sizeof(new_name) - strlen(new_name) - 1);
    
        new_letter[0] = (rand() % CHARACTER_RANGE) + INITIAL_CHARACTER;
        new_letter[1] = '\0';
    
        strncat(new_name, new_letter, sizeof(new_name) - strlen(new_name) - 1);
    
        printf("New string is %s!\n", new_name);
        return 0;
    }
    

    Note however that the call to strcpy is performed without a protection. In this particular example, the source string fits into the destination buffer, but for a more generic approach, there is a simpler method to construct strings within fixed array boundaries with snprintf:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define CHARACTER_RANGE   26
    #define INITIAL_CHARACTER 'A'
    
    int main() {
        char male[] = "A", female[] = "B", new_name[32];
    
        srand(time(NULL));
    
        snprintf(new_name, sizeof new_name, "%s%c",
                 rand() % 2 ? female : male, 
                 rand() % CHARACTER_RANGE + INITIAL_CHARACTER);
    
        printf("New string is %s!\n", new_name);
        return 0;
    }