C Basics: Remove Line Endings Without Trimming Spaces
A name or configuration value may contain meaningful spaces. Remove the line ending without applying a broad whitespace trim.
Prepare a scratch directory
Tested on Linux amd64 with GCC 14.2.0. Install GCC and make gcc available on PATH. You also need Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. This example uses the C standard library.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as trim-line-ending-demo.c:
#include <stdio.h>
#include <string.h>
int main(void) {
char line[] = " two words \r\n";
char unchanged[] = "no newline";
size_t ending_position = strcspn(line, "\r\n");
line[ending_position] = '\0';
unchanged[strcspn(unchanged, "\r\n")] = '\0';
printf("Value: [%s]\n", line);
printf("Length: %zu\n", strlen(line));
printf("Unchanged: [%s]\n", unchanged);
return 0;
}Compile and run it. The second command runs only after compilation succeeds:
gcc -std=c17 -Wall -Wextra -Werror -pedantic trim-line-ending-demo.c -o trim-line-ending-demo &&
./trim-line-ending-demoObserved output:
Value: [ two words ]
Length: 13
Unchanged: [no newline]Read the result
strcspn returns the index of the first CR or LF. Replacing that byte with a null terminator hides the ending and everything after it while preserving leading, internal, and trailing spaces. If no ending is present, the returned length points to the existing terminator.
Apply it carefully
The array must be writable and already null-terminated. Do not use this on an arbitrary binary buffer or a string literal. It cuts at the first CR or LF, so it is appropriate for a single logical line, not a complete multiline document. If input came from fgets, handle read failure and overlong lines separately.
The official reference documents the behavior used here.
Clean up
Remove only the source and executable created for this example, then return to the starting directory:
rm -- trim-line-ending-demo.c trim-line-ending-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect its remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.