The method is tricky as the strtok()
function has side effects on a global hidden state variable. This may affect surrounding code and prove hard to debug.
Furthermore, there is a simple case where strtok(line, "\n")
will not overwrite the '\n'
with a null byte: If the line read by fgets()
is an empty line containing only a single new line byte. For this contents, strtok()
will skip the initial new line, searching for a different character, which is not present, and return NULL
not modifying the array. Hence it will not strip the new line.
This is a compelling reason to not use strtok(line, "\n")
to strip the new line byte.
Of course one can fix this issue by writing:
if (*line == '\n')
*line = '\0';
else
strtok(line, "\n");
Or cumbersome one-liners:
(void)(*line == '\n' ? (*line = '\0') : (strtok(line, "\n"), 0);
if (!strtok(line, "\n")) *line = '\0';
(void)(strtok(line, "\n") || (*line = '\0'));
But the code is no longer compact and still has other side effects.
Other methods are available:
using an explicit for
statement:
for (char *p = line; *p; p++) {
if (*p == '\n')
*p = '\0';
}
using strlen()
:
size_t len = strlen(line);
if (len > 1 && line[len - 1] == '\n') {
line[--len] = '\0';
}
// len is the length if the stripped line
using strchr()
:
char *p = strchr(line, '\n');
if (p) {
*p = '\0';
}
using strcspn()
in a one-liner:
line[strcspn(line, "\n")] = '\0'; // strip the newline if any.
strtok()
which I have seen multiple times recently. – Nimbostratus