The strchr function enables the caller to find the location of the first occurrence of a character in a string.

char *
strchr(const char *s, int c);

The return value is a pointer to the found character, or NULL if it does not exist in the string.

Local Variables

Similar to memchr, the description of strchr is very specific with respect to the data type used for searching. As you see with the prototype, strchr accepts an int as the type being search for. This is partially due to the integer promotion rules, whereby a character being passed as an argument to a function will be implicitly promoted to an int with the same sign. The other part is to maintain compatibility with pre-standardized C code.

"The strchr function locates the first occurrence of c (converted to a char) in the string pointed to by s."

As such, rather than adding casts into our code, we can declare a local char and implicitly cast the searched for character.

const char search = c;

Implementation

We'll use an approach which is slightly similar to strlen where we'll march along the string, comparing each character to search until we find a match or reach the end of the string. One interesting property of this specific function is that it counts the terminating null character as part of the string. This means you can search for null character with strchr. This also means you need to first check for the desired character, and then check against '\0' before exiting the loop. In addition, we get parameter validation for free by using s as the loop condition. Finally, we return NULL if the loop ends as it means we reached the null character without finding a match.

while (s)
{
    if (search == *s)
    {
        return (char *) s;
    }

    if ('\0' == *s)
    {
        break;
    }

    s++;
}

return NULL;

Testing

First, we'll test our parameter validation by passing a NULL pointer, and attempting to search an empty string. Next, we'll search for characters that don't exist at all, or exist past a null character in the array we define. Finally, make sure it works when finding characters at the beginning, middle, and end of the string (i.e. finding the null character).

int
strchrTest(void)
{
    int ret = 1;
    char str[] = "ABCDEFG\0abcdefg";

    do
    {
        /* NULL object */
        if (NULL != strchr(NULL, 'a'))
        {
            break;
        }

        /* Search no characters */
        if (NULL != strchr("", 'a'))
        {
            break;
        }

        /* Search for non-existent character */
        if (NULL != strchr(str, 'Z'))
        {
            break;
        }

        /* Search for char after null character */
        if (NULL != strchr(str, 'a'))
        {
            break;
        }

        /* Valid search at beginning */
        if (str != strchr(str, str[0]))
        {
            break;
        }

        /* Valid search in middle*/
        if ((str + 4) != strchr(str, str[4]))
        {
            break;
        }

        /* Search for null character at end */
        if ((str + strlen(str)) != strchr(str, '\0'))
        {
            break;
        }

        ret = 0;
    } while (0);

    return ret;
}

Conclusion

strchr is straightforward, with the only catch being that the null character is considered a part of the string. Ensuring that it can be found means you could implement strlen by use of strchr.

char *
strchr(const char *s, int c)
{
    const char search  = c;

    while (s)
    {
        if (search == *s)
        {
            return (char *) s;
        }

        if ('\0' == *s)
        {
            break;
        }

        s++;
    }

    return NULL;
}
comments powered by Disqus