strspn
tags: strchr, string.h, strspn
The strspn
function is the opposite of strcspn
in that it computes the
number of characters at the start of a string that are in the set of
characters you specify.
size_t
strspn(const char *s1, const char *s2);
The return value is that count of characters.
While strcspn
is nice for finding the first occurence of any of a given set of
characters, strspn
's use is more for finding the occurence of the first
character not in a given set. This description may seem backwards, but an
example will help.
char *item_nums = { "AA-BC-1234", "AA-321" };
char *set = "ABC-";
size_t loc = strspn(item_nums[0], set);
printf("Serial Number 1: %s\n", loc);
size_t loc = strspn(item_nums[1], set);
printf("Serial Number 2: %s\n", loc);
In this scenario there is an item numbering scheme which consists of the
letters A, B, and C, hyphens, and a serial number. The letters will always
preface the numbers but the number of letters can change. Using strspn
allows
you to easily index to the number.
As a bonus, how else might you solve this problem (hint: strrchr
)?
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
The only error conditions we need to explicitly check for are NULL
pointers,
in both cases the return value will be 0
so they can be handled together.
if (!s1 || !s2)
{
return 0;
}
You might consider empty strings to be another error condition, but the loop logic that follows will handle both situations automatically.
Implementation
The main loop is nearly identical to strcspn
except we want to find a
character with strchr
so we directly use its return value as a loop condition.
The idea is to march along the string being searched and check whether each
character is in the set of characters to find. When we find a character that
isn't in the set then we end our search and return the number of characters that
were found.
while (*s1 &&
strchr(s2, *s1++))
{
len++;
}
return len;
If s1
were empty then the loop body would never execute and 0
would be
returned. If s2
were empty then strchr
would return NULL
and the loop body
wouldn't execute either.
Testing
These tests closely mimic those for strcspn
with slight modifications to error
condition checking.
int
strspnTest(void)
{
int ret = 1;
char str[] = "ABCDEFG";
char str2[] = "ABCD";
do
{
/* NULL source */
if (0 != strspn(NULL, "ABC"))
{
break;
}
/* NULL span set */
if (0 != strspn(str, NULL))
{
break;
}
/* Empty search string */
if (0 != strspn("", "ABCD"))
{
break;
}
/* Empty search set */
if (0 != strspn(str, ""))
{
break;
}
/* Missing characters only */
if (0 != strspn(str, "hijkl"))
{
break;
}
/* Short set of existing characters only */
if (strlen(str2) != strspn(str, str2))
{
break;
}
/* Existing characters only */
if (strlen(str) != strspn(str, str))
{
break;
}
/* Missing character at beginning of search set */
if (strlen(str) != strspn(str, "aABCDEFG"))
{
break;
}
/* Missing character in middle of search set */
if (strlen(str) != strspn(str, "ABCDdEFG"))
{
break;
}
/* Missing character at end of search set */
if (strlen(str) != strspn(str, "ABCDEFGg"))
{
break;
}
ret = 0;
} while (0);
return ret;
}
Conclusion
As seen with the serial number example, strspn
can be used to tell you two
pieces of information about a string: how long the initial set of matching
characters is and at what index non-matching characters start.
size_t
strspn(const char *s1, const char *s2)
{
size_t len = 0;
if (!s1 || !s2)
{
return 0;
}
while (*s1 &&
strchr(s2, *s1++))
{
len++;
}
return len;
}