a shorter strchr

S

Servé Lau

Sometimes I code like this:

char *p = strchr(buf,'\n');
if (p)
*p = 0;

But I've also seen the shorter expression:

buf[strcspn(buf, '\n')] = 0;

Are their advantages to the second one except shorter code?
 
S

Spacen Jasset

Servé Lau said:
Sometimes I code like this:

char *p = strchr(buf,'\n');
if (p)
*p = 0;

But I've also seen the shorter expression:

buf[strcspn(buf, '\n')] = 0;

Are their advantages to the second one except shorter code?

I can't think of any. strcspn might be a bit slower than strchr, because it
is designed to look for a set of characters in a string.

What you have in the second case is slightly wrong, a typo perhaps. strcspn
takes a constant character pointer as it's second argument.
So it should be:
buf[ strcspn(buf, "\n") ] = 0;
 
D

David Rubin

Spacen said:
char *p = strchr(buf,'\n');
if (p)
*p = 0;
[or...]
buf[strcspn(buf, '\n')] = 0;
Are their advantages to the second one except shorter code?
I can't think of any. strcspn might be a bit slower than strchr, because it
is designed to look for a set of characters in a string.

Indeed. Also, "shorter" is relative. What appears shorter to you may be
many times longer to the CPU. Just try to strike a reasonable balance
between terseness and readability. Another idiom is

if((p=strchr(buf, '\n')))
*p = 0;

/david
 
N

nrk

Serv�Lau said:
Sometimes I code like this:

char *p = strchr(buf,'\n');
if (p)
*p = 0;

But I've also seen the shorter expression:

buf[strcspn(buf, '\n')] = 0;

Are their advantages to the second one except shorter code?

The call to strcspn is incorrect. It should be:
buf[strcspn(buf, "\n")] = 0;

One (likely inconsequential) difference is that the second call will always
write a null to the string. There might be some performance trade-offs as
strcspn will be scanning the string for a *set* of characters that it
shouldn't find, while strchr searches for exactly one character which is
considerably more straightforward. Also, as a style issue, I would
probably not go for embedding a function call like that into the index of
an array in the assignment statement.

-nrk.
 
P

pete

Spacen said:
Servé Lau said:
Sometimes I code like this:

char *p = strchr(buf,'\n');
if (p)
*p = 0;

But I've also seen the shorter expression:

buf[strcspn(buf, '\n')] = 0;

Are their advantages to the second one except shorter code?

I can't think of any.
strcspn might be a bit slower than strchr, because it
is designed to look for a set of characters in a string.

Conceptually, strcspn can be described as looping calls to strchr.

size_t strcspn(const char *s1, const char *s2)
{
const char *const p1 = s1;

while (strchr(s2, *s1) == NULL) {
++s1;
}
return s1 - p1;
}
What you have in the second case is slightly wrong,
a typo perhaps. strcspn
takes a constant character pointer as it's second argument.
So it should be:
buf[ strcspn(buf, "\n") ] = 0;

A briefer, more computationally intensive way of writing it would be:

strtok(buf, "\n");
 
D

Dan Pop

In said:
Sometimes I code like this:

char *p = strchr(buf,'\n');
if (p)
*p = 0;

But I've also seen the shorter expression:

buf[strcspn(buf, '\n')] = 0;

Are their advantages to the second one except shorter code?

It's neither more readable nor likely to be faster at run time.

If you're fond of oneliners, yours can be turned into one, too:

(p = strchr(buf,'\n')) ? (*p = 0) : 0;
or
if ((p = strchr(buf,'\n')) != NULL) *p = 0;

Dan
 
D

Dan Pop

In said:
However, this is not readable at all since the intent is unclear and the
effect is merely a byproduct of the function's semantics.

I disagree: the return value being ignored, it is (or should be) OBVIOUS
that this function was called *exclusively* for its side effect(s).

Dan
 
S

Spacen Jasset

....
A briefer, more computationally intensive way of writing it would be:

strtok(buf, "\n");

That does not work how the other methods do though. In particular, it would
not remove '\n' at the begining of the string. From the NetBSD man pages:

" The strtok() function returns a pointer to the beginning of each subse-
quent token in the string, after replacing the separator character
itself
with a NUL character. Separator characters at the beginning of the
string or at the continuation point are skipped so that zero length to-
kens are not returned. When no more tokens remain, a null pointer is
re-
turned."
 
P

pete

Spacen said:
...


That does not work how the other methods do though.
In particular, it would
not remove '\n' at the begining of the string.

Good catch. Thank you.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top