The strcat function allows you to join two strings by appending the second string to the first, modifying the first string rather than creating a new one.

char *
strcat(char *s1, const char *s2);

It will return s1 which will now hold the concatenation of the two strings.

Implementation

To concatenate two strings means copying one to the end of the other. To find the end of the first string we use the strlen function to get an index for the location of the terminating null character. Then we pass this location to strcpy, providing the second string as the second parameter.

strcpy(s1 + strlen(s1), s2);
return s1;

We don't need any parameter validation because strlen and strcpy do that for us. If s1 is NULL then strlen will return 0 and we'll end up passing NULL to strcpy which will return without modifying anything. Likewise, if s2 is NULL then strcpy won't do anything.

Testing

We need to test concatenation to/from NULL pointers, to/from empty strings, and finally normal concatenation. In the case of NULL pointers and an empty source string, we expect the destination to be unmodified. Otherwise, we verify that the result is the second string appended to the first.

int
strcatTest(void)
{
    int ret         = 1;
    char *pStr1     = NULL;
    char pStr2[15]  = "hello, world";
    char pStr3[15]  = "hello, world";
    char pStr4[15]  = { 0 };
    char pStr5[15]  = "hello,";
    char *pStr6     = " world";

    do
    {
        /* Append to NULL, may crash */
        strcat(pStr1, pStr2);

        /* Concatenate from NULL, may crash */
        strcat(pStr2, pStr1);

        /* Concatenate to an empty string */
        strcat(pStr4, pStr2);
        if (0 != memcmp(pStr4, pStr2, strlen(pStr2)))
        {
            break;
        }

        /* Concatenate from an empty string */
        memset(pStr4, '\0', sizeof(pStr4));
        strcat(pStr2, pStr4);
        if (0 != memcmp(pStr2, pStr3, sizeof(pStr3)))
        {
            break;
        }

        /* Normal concatenation */
        strcat(pStr5, pStr6);
        if (0 != memcmp(pStr5, pStr2, sizeof(pStr2)))
        {
            break;
        }

        ret = 0;
    } while (0);

    return ret;
}

Conclusion

As our library continues to grow, we'll find that more and more functions can be implemented in terms of existing functions. This will reduce the logic and validation required so that it becomes concentrated in certain parts of the library. It also means that there is less code to debug later on if there are any problems.

char *
strcat(char *s1, const char *s2)
{
    strcpy(s1 + strlen(s1), s2);
    return s1;
}
comments powered by Disqus