patterncMinor
A trivial command line utility for trimming whitespace from lines in C
Viewed 0 times
linewhitespacetrimmingutilitytrivialforcommandfromlines
Problem
I was practicing some C and decided to write this simple command line utility for stripping leading and trailing white-space characters.
Note: see the next iteration at A trivial command line utility for trimming whitespace from lines in C - follow-up
The code:
```
#include
#include
#include
#include
#define LINE_LENGTH 8096
#define HELP_MESSAGE "Usage: trim [FILE1, [FILE2, [...]]]\n" \
" If no files specified, reads from standard input.\n"
#define VERSION_MESSAGE "trim 1.6\n" \
"By Rodion \"rodde\" Efremov. 07.04.2015 Helsinki\n"
#define HELP_FLAG "-h"
#define VERSION_FLAG "-v"
/*****
This routine removes all leading and trailing whitespace from a string,
doing that in-place. (
/
static char trim_inplace(char const start)
{
size_t leading_ws_chars = 0;
size_t trailing_ws_chars = 0;
size_t len;
size_t i;
// Find amount of leading whitespace characters.
while (isspace(*(start + leading_ws_chars)))
{
++leading_ws_chars;
}
// Find the length of the entire string.
len = leading_ws_chars;
while (start[len])
{
++len;
}
if (len == leading_ws_chars)
{
// Empty string.
start[0] = '\0';
}
// Here 'start[len] == NULL'.
while (isspace(*(start + len - 1 - trailing_ws_chars)))
{
++trailing_ws_chars;
}
// Shift the text to the left.
for (i = 0; i < len - leading_ws_chars - trailing_ws_chars; ++i)
{
start[i] = start[i + leading_ws_chars];
}
// Terminate.
start[len - leading_ws_chars - trailing_ws_chars] = '\0';
return start;
}
/*****
* Processes a file.
Note: see the next iteration at A trivial command line utility for trimming whitespace from lines in C - follow-up
The code:
```
#include
#include
#include
#include
#define LINE_LENGTH 8096
#define HELP_MESSAGE "Usage: trim [FILE1, [FILE2, [...]]]\n" \
" If no files specified, reads from standard input.\n"
#define VERSION_MESSAGE "trim 1.6\n" \
"By Rodion \"rodde\" Efremov. 07.04.2015 Helsinki\n"
#define HELP_FLAG "-h"
#define VERSION_FLAG "-v"
/*****
This routine removes all leading and trailing whitespace from a string,
doing that in-place. (
/
static char trim_inplace(char const start)
{
size_t leading_ws_chars = 0;
size_t trailing_ws_chars = 0;
size_t len;
size_t i;
// Find amount of leading whitespace characters.
while (isspace(*(start + leading_ws_chars)))
{
++leading_ws_chars;
}
// Find the length of the entire string.
len = leading_ws_chars;
while (start[len])
{
++len;
}
if (len == leading_ws_chars)
{
// Empty string.
start[0] = '\0';
}
// Here 'start[len] == NULL'.
while (isspace(*(start + len - 1 - trailing_ws_chars)))
{
++trailing_ws_chars;
}
// Shift the text to the left.
for (i = 0; i < len - leading_ws_chars - trailing_ws_chars; ++i)
{
start[i] = start[i + leading_ws_chars];
}
// Terminate.
start[len - leading_ws_chars - trailing_ws_chars] = '\0';
return start;
}
/*****
* Processes a file.
Solution
I can't help you with GNU style, but here are some things that may help you improve your code.
Close files when you are done with them
The program will automatically close files when the program terminates, but it's good to close them as soon as you're done with them. This helps prevent the problem of running out of file handles.
Simplify the
The
Don't use
The program declares this function:
But that doesn't make much sense. It says "I can alter the characters, but I won't alter the pointer" but that doesn't really make much sense because the pointer is passed by value anyway. The same is true for the
See this SO question for details on that latter point.
Consider handling arbitrarily long lines
As the program is currently written, it has an arbitrary limit of 8096 characters for a line. If I have a line with 8094 spaces followed by the string "ab", the program will trim the spaces, but put "a" and "b" on separate lines in the output. The program could easily be rewritten to handle character at a time input and eliminate the arbitrary line limit.
Eliminate
For a long time now, the C language says that finishing
Close files when you are done with them
The program will automatically close files when the program terminates, but it's good to close them as soon as you're done with them. This helps prevent the problem of running out of file handles.
Simplify the
trim_inplace functionThe
trim_inplace function can be simplfified considerably. One possibility is this:static char* trim_inplace(char *start)
{
// handle empty line per @Snowbody's commment
if (strlen(start) == 0)
return start;
for (char *end = &start[strlen(start)-1]; isspace(*end); --end)
*end = '\0';
while (isspace(*start))
++start;
return start;
}Don't use
const if you don't mean itThe program declares this function:
static char* trim_inplace(char *const start)But that doesn't make much sense. It says "I can alter the characters, but I won't alter the pointer" but that doesn't really make much sense because the pointer is passed by value anyway. The same is true for the
process_file argument.See this SO question for details on that latter point.
Consider handling arbitrarily long lines
As the program is currently written, it has an arbitrary limit of 8096 characters for a line. If I have a line with 8094 spaces followed by the string "ab", the program will trim the spaces, but put "a" and "b" on separate lines in the output. The program could easily be rewritten to handle character at a time input and eliminate the arbitrary line limit.
Eliminate
return EXIT_SUCCESS at the end of mainFor a long time now, the C language says that finishing
main will implicitly generate the equivalent to return EXIT_SUCCESS. For that reason, you should eliminate that line from your code.Code Snippets
static char* trim_inplace(char *start)
{
// handle empty line per @Snowbody's commment
if (strlen(start) == 0)
return start;
for (char *end = &start[strlen(start)-1]; isspace(*end); --end)
*end = '\0';
while (isspace(*start))
++start;
return start;
}static char* trim_inplace(char *const start)Context
StackExchange Code Review Q#86140, answer score: 6
Revisions (0)
No revisions yet.