HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Trimming fgets(): strlen() or strtok()

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
trimmingstrtokfgetsstrlen

Problem

After a successful 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 another strtok() sequence.

Solution

For what it is worth, using 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.