strcspn
tags: strchr, strcspn, string.h, strlen
The strcspn
function is like an advanced version of strchr
- it determines
the number of characters at the start of a string are not in the set of
characters you specify.
size_t
strcspn(const char *s1, const char *s2);
The return value is that count of characters.
This function is somewhat confusing so it will help to show an example. Using
strcspn
allows you to answer a question like "Where does the first instance of
a, b, or c occur in the string 'Goodbye, cruel world'?". C code which answers
this question would look like so:
char *phrase = "Goodbye, cruel world";
char *set = "abc";
size_t loc = strcspn(phrase, set);
printf("The first instance is at index %u", len);
At this point, loc
will either be equal to the length of the phrase, implying
that a, b, or c does not exist in the string, or it will hold the index of the
first occurrence of either of those characters. We can see that there is a 'b'
in "Goodbye", so the message printed to the screen will be "The first instance
is at index 4".
Local Variables
There isn't much to keep track of since we're only calculating a length, so
we'll create a variable of type size_t
to hold that information which is also
the return value.
size_t len = 0;
Error Checking
There are two error cases we need to account for and each requires a different
return value. The first case is when the string being searched, s1
, is NULL
.
If this is the case then the string has no length and the return value would be
0
.
if (!s1)
{
return 0;
}
The second case is when no search characters are provided, i.e. s2
is NULL
.
Since we don't have anything to search for then the return value is equal to the
length of the string being searched.
if (!s2)
{
return strlen(s1);
}
The order of these checks is important as well. The first case implies that we can't do any searching while the seconds implies that we don't need to do any searching.
Implementation
The method we'll use is to march along the first string and look for each
subsequent character in the second string. We'll keep marching until we reach
the end of the string being searched or we find a match. The hardest part here
is finding matches but we can farm that work out to strchr
since that's
exactly what it's for! As long as we continue marching then we also continue
updating the count being returned.
while (*s1 &&
!strchr(s2, *s1++))
{
len++;
}
return len;
Testing
First, we'll test our parameter validation by passing a NULL
pointer for each
of the strings in sequence and similarly pass empty strings for each. Next,
we'll search for characters that don't exist at all to ensure that we get the
length of the search string back. Finally, we'll place the first-matched
character at various positions in the string of characters being matched
against.
int
strcspnTest(void)
{
int ret = 1;
char str[] = "ABCDEFGabcdefg";
do
{
/* NULL source */
if (0 != strcspn(NULL, "ABC"))
{
break;
}
/* NULL span complement */
if (strlen(str) != strcspn(str, NULL))
{
break;
}
/* Empty search string */
if (0 != strcspn("", "ABCD"))
{
break;
}
/* Empty search set */
if (strlen(str) != strcspn(str, ""))
{
break;
}
/* Characters aren't in string */
if (strlen(str) != strcspn(str, "hijkl"))
{
break;
}
/* First character is in the search set */
if (0 != strcspn(str, "A"))
{
break;
}
/* Character at beginning of search set */
if (3 != strcspn(str, "Dabcd"))
{
break;
}
/* Character in middle of search set */
if (3 != strcspn(str, "abDcd"))
{
break;
}
/* Character at end of search set */
if (3 != strcspn(str, "abcdD"))
{
break;
}
ret = 0;
} while (0);
return ret;
}
Conclusion
Although the description is somewhat confusing, strcspn
is not difficult to
implement. The name comes from "string complement span" because it computes the
span of characters in a string that are in the set complementary to the one
provided.
size_t
strcspn(const char *s1, const char *s2)
{
size_t len = 0;
if (!s1)
{
return 0;
}
if (!s2)
{
return strlen(s1);
}
while (*s1 &&
!strchr(s2, *s1++))
{
len++;
}
return len;
}