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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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. *
*******************************************************************************/
static void process_file(FILE *const file)
{
char line[LINE_LENGTH];
if (file == NULL)
{
perror("Error opening file");
exit(EXIT_FAILURE);
}
while (fgets(line, LINE_LENGTH, file) != NULL)
{
printf("%s\n", trim_inplace(line));
}
}
/*******************************************************************************
* Prints the help message and exits. *
*******************************************************************************/
static void print_help()
{
printf(HELP_MESSAGE);
exit(EXIT_SUCCESS);
}
/*******************************************************************************
* Prints the version string. *
*******************************************************************************/
static void print_version()
{
printf(VERSION_MESSAGE);
exit(EXIT_SUCCESS);
}
/*******************************************************************************
* Checks the flags. *
*******************************************************************************/
static void check_flags(int argc, char** argv)
{
size_t i;
for (i = 1; i < argc; ++i)
{
if (strcmp(argv[i], HELP_FLAG) == 0)
{
print_help();
}
else if (strcmp(argv[i], VERSION_FLAG) == 0)
{
print_version();
}
}
}
/*******************************************************************************
* The entry point for a trivial line trimmer. *
*******************************************************************************/
int main(int argc, char** argv)
{
size_t i;
FILE* file;
check_flags(argc, argv);
if (argc < 2)
{
process_file(stdin);
return EXIT_SUCCESS;
}
else
{
for (i = 1; i < argc; ++i)
{
file = fopen(argv[i], "r");
if (!file)
{
perror("Error opening a file");
return (EXIT_FAILURE);
}
process_file(file);
}
}
return (EXIT_SUCCESS);
}
My question: how to make this utility conform to GNU style of doing software?