The strncmp function allows you to compare to strings to determine their (in)equality while also specifying a maximum number of characters to compare.

int
strncmp(const char *s1, const char *s2, size_t n);

The return value is an integer which indicates whether the first string is greater than, equal to, or less than the second string.

Implementation

strncmp is of course similar to strcmp, but we first need to determine how many characters should be compared, as any characters after a null-character in s1 should not be compared. Therefore, we need to determine the length of s1, plus 1 for the null-character, and compare a number of characters which is the lesser of that value and n. We can then pass the real work on to memcmp.

size_t len1 = strlen(s1) + 1;

if (len1 < n)
{
    n = len1;
}

return memcmp(s1, s2, n);

It's important to include the + 1 as otherwise an s1 which is a substring of s2 would compare as equal (e.g. strncmp("foo", "foobar", strlen("foobar"))).

Testing

We need to test comparison to/from NULL pointers, to/from empty strings, and all cases of equal, greater than, and less than results. The only deviation from the strcmp tests is comparing two strings where one is a substring of the other. Performing this test ensures that the null-character is accounted for when s1 is shorter than s2.

int
strncmpTest(void)
{
    int ret         = 1;
    char pStr1[]    = "This is a Test string";
    char pStr2[]    = "This is a Test string";
    char pStr3[]    = "This is a Lesser string";
    char pStr4[]    = "This is a greater string";
    char *pStr5     = NULL;
    char pStr6[]    = "This is a Test string with more";

    do
    {
        /* NULL s2 pointer */
        if (1 != strncmp(pStr1, pStr5, sizeof(pStr1)))
        {
            break;
        }

        /* NULL s1 pointer */
        if (1 != strncmp(pStr5, pStr1, sizeof(pStr1)))
        {
            break;
        }

        /* Empty s2 */
        if (0 >= strncmp(pStr1, "", sizeof(pStr1)))
        {
            break;
        }

        /* Empty s1 */
        if (0 <= strncmp("", pStr1, sizeof(pStr1)))
        {
            break;
        }

        /* Test equality */
        if (0 != strncmp(pStr1, pStr2, sizeof(pStr1)))
        {
            break;
        }

        /* Test equal substrings */
        if (0 != strncmp(pStr1, pStr6, sizeof(pStr1) - 1))
        {
            break;
        }

        /* Test inequal strings */
        if (0 == strncmp(pStr1, pStr6, sizeof(pStr1)))
        {
            break;
        }

        /* First string greater than second string */
        if (0 >= strncmp(pStr1, pStr3, sizeof(pStr1)))
        {
            break;
        }

        /* First string less than second string */
        if (0 <= strncmp(pStr1, pStr4, sizeof(pStr1)))
        {
            break;
        }

        ret = 0;
    } while (0);

    return ret;
}

Conclusion

Again, memcmp does all the work and we need to take care when calculating the maximum number of characters to be compared.

int
strncmp(const char *s1, const char *s2, size_t n)
{
    size_t len1 = strlen(s1) + 1;

    if (len1 < n)
    {
        n = len1;
    }

    return memcmp(s1, s2, n);
}
comments powered by Disqus