Re: equivalent of chomp in perl
- From: Flash Gordon <spam@xxxxxxxxxxxxxxxxxx>
- Date: Sat, 04 Nov 2006 06:23:04 +0000
Jordan Abel wrote:
2006-11-03 <lnslh0kvgb.fsf@xxxxxxxxxxxxxxx>,
Keith Thompson wrote:
Jordan Abel <random@xxxxxxxxxxxxx> writes:
[...]
Anyway, in answer to the questionNot quite.
void
chomp(char *x) {
char *p = strrchr(x,'\n');
if(p) *p = 0;
}
Let's look at the definition from the Camel Book (the canonical book
on Perl, comparable to K&R). This is arguably a little off-topic, but
it's a good example of the pitfalls of emulating features of one
language in another language.
chomp VARIABLE
chomp LIST
chomp
This function (normally) deletes a trailing newline from the end
of a string contained in a variable. This is a slightly safer
version of chop (described next) in that it has no effect upon a
string that doesn't end in a newline. More specifically, it
deletes the terminating string corresponding to the current value
of $/, and not just any last character.
Unlike chop, chomp returns the number of characters deleted. If $/
is "" (in paragraph mode), chomp removes all trailing newlines
from the selected string (or strings, if chomping a LIST). You
cannot chomp a literal, only a variable.
Some of the features of chomp aren't applicable to a C version: it can
be applied to either a list or a single variable, and the argument
defaults to $_ (if you're not familiar with Perl, don't worry about
what that means). And C has no equivalent to $/ (which in Perl lets
you set the input record separator to something other than the default
"\n").
So a reasonable C chomp() would operate on a single string, would
remove the last character if and only if it's a '\n', and would return
1 if it removed a character and 0 if it didn't.
Jordan, your version clobbers the last '\n' in the string, even if
it's not at the end of the string.
Here's my attempt:
int chomp(char *s)
{
size_t len = strlen(s);
if (len == 0) {
return 0;
}
else if (s[len-1] == '\n') {
s[len-1] = '\0';
return 1;
}
else {
return 0;
}
}
I did mess up.
How about
chomp(s)
char *s;
{
Why use old style function definitions? It is very rare these days to find a compiler that does not handle prototypes.
int chomp(char *s)
if(s && *s) {
char *p = strrchr(s,0);
I can't see any reason for strrchr to be noticeably faster than strlen and it could be slower if the compiler does not do clever handling of that call. After all, it has to find the end of the string before starting to scan backwards for a value of 0 (which it will find on the first check) and all strlen has to do is find the end of the string either counting as it goes or doing a pointer subtraction at the end.
if(p[-1]=='\n') {
p[-1]=0;
return 1;
}
}
return 0;
}
may be slightly more efficient than yours if the compiler doesn't get especially clever with strlen calls.
I don't think it is likely to be faster. It has the advantage of being shorter than Keith's but you can achieve that by using
int chomp(char *s)
{
if(s && *s) {
s += strlen(s) - 1;
if (*s == '\n') {
*s = 0;
return 1;
}
}
return 0;
}
I don't expect any significant performance improvement, however if you want micro-optimisations which is all I see in yours over Keith's I've removed the need for the extra complexity of strrchr over strlen and removed the need to index in to an array twice by doing one subtraction.
I prefer a version using strlen to strrchr myself, but this is because to me it expresses the intent better rather than for reasons of efficiency since I don't see any of them as having significant efficiency problems.
Now for an even shorter version that I would *not* put in real code
int chomp(char *s)
{
return (s && *s && *(s += strlen(s) - 1) == '\n')?!(*s = 0):0;
}
I threw in null pointer handling because it's practically free.
Agreed, and that matches the Perl chomp better since the Perl chomp will not crash on being passed an undef (the nearest Perl equivalent to passing a null pointer instead of a string).
You could add an int INPUT_RECORD_SEPARATOR; variable, but for it to be useful you'd need an fgets replacement.
To get the equivalent of Perl reading a line from a file you would need an fgets replacement anyway, of which a few have been posted to this group in the past some of which could easily be modified to suit.
--
Flash Gordon
.
- Follow-Ups:
- Re: equivalent of chomp in perl
- From: Jordan Abel
- Re: equivalent of chomp in perl
- References:
- equivalent of chomp in perl
- From: lnatz
- Re: equivalent of chomp in perl
- From: CBFalconer
- Re: equivalent of chomp in perl
- From: Keith Thompson
- Re: equivalent of chomp in perl
- From: CBFalconer
- Re: equivalent of chomp in perl
- From: Keith Thompson
- Re: equivalent of chomp in perl
- From: Jordan Abel
- Re: equivalent of chomp in perl
- From: Keith Thompson
- Re: equivalent of chomp in perl
- From: Jordan Abel
- equivalent of chomp in perl
- Prev by Date: Re: bit shifts across array elements
- Next by Date: Re: Cannot return values of char variable
- Previous by thread: Re: equivalent of chomp in perl
- Next by thread: Re: equivalent of chomp in perl
- Index(es):
Relevant Pages
|
|