patterncMinor
Trimming fgets(): strlen() or strtok()
Viewed 0 times
trimmingstrtokfgetsstrlen
Problem
After a successful
Of the following 2 methods, are there any shortcomings?
Notes:
fgets(buffer, ...), it is often desirable to trim a potential End-of-Line '\n'.Of the following 2 methods, are there any shortcomings?
#include
char buffer[100];
// Method 1
while (fgets(buffer, sizeof buffer, stdin) != NULL) {
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n')
buffer[--len] = '\0';
// use buffer
printf("\"%s\"\n", buffer);
}
// Method 2
while (fgets(buffer, sizeof buffer, stdin) != NULL) {
strtok(buffer, "\n");
// use buffer
printf("\"%s\"\n", buffer);
}Notes:
- When reading text files from alternate file systems,
strtok(buffer, "\r\n")looks useful.
strtok()may incur an issue with anotherstrtok()sequence.
Solution
For what it is worth, using
It surprised me that to execute this neat looking thing:
takes nearly 50% longer than this ugly looking sucker:
and the beautiful
and
are 10 to 20 times slower. The latter two do of course look for \r as well as \n. But even adding \r, the
Note that I wasn't exhaustive with string variations. In fact I didn't even break a sweat. And of course this is all quite irrelevant as the
Note also from the comments below that if the first character of the search string (
strlen is much more efficient than using strtok. I did some tests (omitting the file access) using strlen, strchr, strtok, strstr, strpbrk and strcspn:It surprised me that to execute this neat looking thing:
s = strchr(s, '\n');
if (s) {
*s = '\0';
}takes nearly 50% longer than this ugly looking sucker:
size_t len = strlen(s);
if (len && (s[len-1] == '\n')) {
s[len-1] = '\0';
}and the beautiful
strtok(s, "\n\r");and
strsep(&s, "\n\r");are 10 to 20 times slower. The latter two do of course look for \r as well as \n. But even adding \r, the
strlen approach is still quicker than the strchr and still quicker then strtok and strsep by 10 to 20 times:size_t len = strlen(s);
if (len && ((s[len-1] == '\n') || (s[len-1] == '\r'))) {
s[len-1] = '\0';
}Note that I wasn't exhaustive with string variations. In fact I didn't even break a sweat. And of course this is all quite irrelevant as the
stdio call will dominate in your target code :-)Note also from the comments below that if the first character of the search string (
s in the examples above) is one of the characters in the pattern string, strtok does nothing (thanks to @chux).Code Snippets
s = strchr(s, '\n');
if (s) {
*s = '\0';
}size_t len = strlen(s);
if (len && (s[len-1] == '\n')) {
s[len-1] = '\0';
}strtok(s, "\n\r");strsep(&s, "\n\r");size_t len = strlen(s);
if (len && ((s[len-1] == '\n') || (s[len-1] == '\r'))) {
s[len-1] = '\0';
}Context
StackExchange Code Review Q#67608, answer score: 8
Revisions (0)
No revisions yet.