strrchr
tags: strchr, string.h, strrchr
The strrchr
function enables the caller to find the location of the last
occurrence of a character in a string.
char *
strrchr(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
We use a char
search character for the same reason mentioned for strchr
.
Otherwise, we only need a pointer to the end of the string so we can search in
the reverse direction.
const char *cur = NULL;
const char search = c;
Implementation
The implementation is similar to that of strrchr
, but performed in the reverse
direction. We use the beginning of the string as our terminal position, rather
than that of the null-character. Another difference is that we first determine
where the end of the string is, which we can rely on strlen
to calculate for
us.
The only catch to this function is that since the null-character is considered
part of the search, we must ensure we compare that character every time - even
if the string is empty (i.e. the string points to the null-character). This is
where the --cur
becomes important. When an empty string is searched, by
pre-decrementing we ensure that we only inspect the null-character rather than
looping an extra time (which would happen if post-decrement, cur--
, was used).
if (!s)
{
return NULL;
}
cur = s + strlen(s);
do
{
if (search == *cur)
{
return (char *) cur;
}
} while (--cur >= s);
return NULL;
Testing
First, we'll test our parameter validation by passing a NULL
pointer, and
attempting to search an empty string which should succeed when we search for the
null-character. 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), as well as finding the last occurrence of a
character which occurs multiple times in the string.
int
strrchrTest(void)
{
int ret = 1;
char str[] = "ABCDEFGBCDEFG\0abcdefg";
char emptyStr[] = "";
do
{
/* NULL object */
if (NULL != strrchr(NULL, 'a'))
{
break;
}
/* Search empty string for characters */
if (NULL != strrchr(emptyStr, 'a'))
{
break;
}
/* Search empty string for the null-character */
if (emptyStr != strrchr(emptyStr, '\0'))
{
break;
}
/* Search for non-existent character */
if (NULL != strrchr(str, 'Z'))
{
break;
}
/* Search for char after null character */
if (NULL != strrchr(str, 'a'))
{
break;
}
/* Valid search at beginning */
if (str != strrchr(str, str[0]))
{
break;
}
/* Valid search in middle*/
if (strchr(str + 2, str[1]) != strrchr(str, str[1]))
{
break;
}
/* Valid search at end */
if ((str + strlen(str) - 1) != strrchr(str, str[strlen(str) - 1]))
{
break;
}
/* Search for null character at end */
if ((str + strlen(str)) != strrchr(str, '\0'))
{
break;
}
ret = 0;
} while (0);
return ret;
}
Conclusion
strrchr
is the reverse analogue of strchr
with the same catch about finding
the null-character.
char *
strrchr(const char *s, int c)
{
const char *cur = NULL;
const char search = c;
if (!s)
{
return NULL;
}
cur = s + strlen(s);
do
{
if (search == *cur)
{
return (char *) cur;
}
} while (--cur >= s);
return NULL;
}