How To Remove Trailing Newline Character From fgets Input
Updated:
Let’s say we have to process a text file line by line, and we have to make sure that the line we are processing does not end with a newline character. Let’s acquire each line using the fgets function and see what we get.
#include <stdio.h>
#include <stdlib.h>
#define LINE_MAX_LEN 100
int main() {
int line_counter = 0;
char line[LINE_MAX_LEN + 1] = {[LINE_MAX_LEN] = '\0'};
FILE *fp = fopen("file_to_process", "r");
while (fp && fgets(line, LINE_MAX_LEN, fp)) {
printf("line %d: <%s>\n", line_counter++, line);
}
}
Let’s start from the beginning
Looking at the definition of line, we see that its length is one character longer than LINE_MAX_LEN, and the last element is initialized to '\0'. This special character is used as string terminator in C and is called the null character. If a string did not have a null character to terminate it, it could break the program. So, limiting the acquisition to LINE_MAX_LEN when we call fgets, we also ensure that at least the last element of line is a null character, since it can’t be touched by fgets.
The permanence condition inside the while loop is that fp is different from NULL (so we opened the file smoothly) and that the return value of fgets is also different from NULL (so we have correctly read a line from fp). Also, remember that the && operator is shorthanded, so if fp is NULL, no call to fgets actually takes place, and the loop breaks immediately.
It’s time to read a file
Let’s say we have a file_to_process containig this text:
Hello world, this is the first line.
And here is the second.
And so on.
Over and over again.
Cheers!
When we run our program we get this output:
line 0: <Hello world, this is the first line.
>
line 1: <And here is the second.
>
line 2: <And so on.
>
line 3: <Over and over again.
>
line 4: <Cheers!
>
We see that before printing > the output wraps on a new line. So, let’s try to fix it.
Trimming the trailing newline character
The best and most elegant way to remove the trailing newline character is by using the strcspn function.
line[strcspn(line, "\n")] = '\0';
If you read some documentation and reason a little bit, you can understand that in our case this function returns the position of the first newline character in line. If not found, it returns the position of the fist null character in line (so, its end). Now we see that we can safely set this element to '\0', whether '\n' was found or not, and we are done.
Here is the complete final program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_MAX_LEN 100
int main() {
int line_counter = 0;
char line[LINE_MAX_LEN + 1] = {[LINE_MAX_LEN] = '\0'};
FILE *fp = fopen("file_to_process", "r");
while (fgets(line, LINE_MAX_LEN, fp)) {
line[strcspn(line, "\n")] = '\0';
printf("line %d: <%s>\n", line_counter++, line);
}
}
And here is the result we get when we run it. Now we see that the newline character has been removed!
line 0: <Hello world, this is the first line.>
line 1: <And here is the second.>
line 2: <And so on.>
line 3: <Over and over again.>
line 4: <Cheers!>