You should be passing char const* around; you should be using size_t, not int. Calculating strlen() in advance is more work that necessary: just iterate until you encounter the \0 byte at the end of the string (which is what strlen() does). You're also not checking for the cases where target is longer than string which means your code will likely core dump.
Here's a simpler (and correct) implementation of starts_with():
I love learning math (*to some extent*), CS theory, good literature, and the technology that provides me with all kinds of resources for them: the web.
Thank you for pointing these out. I only have a very basic understanding of C from a general introductory course, so I should've probably not even attempted writing about it in the article.
But, I'm not sure how I could avoid using strlen() here, and do it in a similar way to your starts_with().
I'll update the article later on, and also would like to apologize for being quick to write a C example while still being quite the beginner, but, lesson learned. Thank you.
Nope. size_t is an unsigned type. If target is longer than string, you'll end up with a very large positive number.
For ends_with(), the simplest solution does use strlen():
bool ends_with( char const *s, char const *t ) {
size_t const s_len = strlen( s );
size_t const t_len = strlen( t );
return t_len <= s_len && strcmp( s + s_len - t_len, t ) == 0;
}
However, that's slightly inefficient. If t_len is much longer than s_len, then you've wasted time traversing to the end of t. This version is more efficient:
You're determining t_lenwhile checking to see if you've gone past the end of s: if you have, then s can't end with t and you can just stop immediately. After, you scan for the end of s. Once you find it, then finally check for a match.
I love learning math (*to some extent*), CS theory, good literature, and the technology that provides me with all kinds of resources for them: the web.
The first example made perfect sense, but I struggle with for ( ; s[ t_len ] != '\0'; ++s ); line from the second one.
So, in the second version, with an example string being "hey" and target being "ey", t_len would be 2, if I understand it right. Since "ey" is not longer than "hey", we don't return false immediately. But, doesn't incrementing s until the length of target in the first for loop mean that s is now only at the last character "y". So, s[t_len] confused me.
Also, is s0 needed since it's not used here?
Sorry for asking noob questions, I'm surely missing a lot and confusing myself but trying to understand it, now even regret writing the example in the first place. Thank you for your time and patience.
You are correct: s0 is not needed. (It was left over from an earlier version.) You've also found a bug. (Even "simple" code like this can be tricky!) I've edited the code with a corrected version.
I love learning math (*to some extent*), CS theory, good literature, and the technology that provides me with all kinds of resources for them: the web.
You should be passing
char const*
around; you should be usingsize_t
, notint
. Calculatingstrlen()
in advance is more work that necessary: just iterate until you encounter the\0
byte at the end of the string (which is whatstrlen()
does). You're also not checking for the cases wheretarget
is longer thanstring
which means your code will likely core dump.Here's a simpler (and correct) implementation of
starts_with()
:I'll leave a simpler (and correct) implementation of
ends_with()
as an exercise for the reader.Thank you for pointing these out. I only have a very basic understanding of C from a general introductory course, so I should've probably not even attempted writing about it in the article.
I guess
ends_with()
could also work like this:But, I'm not sure how I could avoid using
strlen()
here, and do it in a similar way to yourstarts_with()
.I'll update the article later on, and also would like to apologize for being quick to write a C example while still being quite the beginner, but, lesson learned. Thank you.
Nope.
size_t
is an unsigned type. Iftarget
is longer thanstring
, you'll end up with a very large positive number.For
ends_with()
, the simplest solution does usestrlen()
:However, that's slightly inefficient. If
t_len
is much longer thans_len
, then you've wasted time traversing to the end oft
. This version is more efficient:You're determining
t_len
while checking to see if you've gone past the end ofs
: if you have, thens
can't end witht
and you can just stop immediately. After, you scan for the end ofs
. Once you find it, then finally check for a match.The first example made perfect sense, but I struggle with
for ( ; s[ t_len ] != '\0'; ++s );
line from the second one.So, in the second version, with an example string being "hey" and target being "ey",
t_len
would be 2, if I understand it right. Since "ey" is not longer than "hey", we don't return false immediately. But, doesn't incrementings
until the length of target in the first for loop mean that s is now only at the last character "y". So,s[t_len]
confused me.Also, is
s0
needed since it's not used here?Sorry for asking noob questions, I'm surely missing a lot and confusing myself but trying to understand it, now even regret writing the example in the first place. Thank you for your time and patience.
You are correct:
s0
is not needed. (It was left over from an earlier version.) You've also found a bug. (Even "simple" code like this can be tricky!) I've edited the code with a corrected version.Thank you, again, for your help. I updated the article with the correct versions.