This is useful for text filters, such as a program that prints only lines with palindromes to specify input files through command line arguments, for example, it allows:
$ palindromes input*.txt
This is a common convention that is supported by many languages. The following are scripts in Perl, Python, C that have the same use:
Usage: palindromes [FILE]
Print lines that are polindromes in each FILE.
With no FILE, or when FILE is -, read standard input.
in perl
#!/usr/bin/perl -w while (<>) { # read stdin or file(s) specified at command line $line = $_; s/^\s+
in python
#!/usr/bin/env python import fileinput, sys for line in fileinput.input(): # read stdin or file(s) specified at command line s = line.strip() # strip whitespace characters if s == s[::-1]: # is palindrome sys.stdout.write(line)
in C
#!/usr/local/bin/tcc -run -Wall #include <ctype.h> #include <errno.h> #include <stdbool.h> #include <stdio.h> #include <string.h> enum { MATCH, NO_MATCH, ERROR }; bool is_palindrome(char *first, char *last) { /** Whether a line defined by range [first, last) is a palindrome. `last` points either to '\0' or after the last byte if there is no '\0'. Leading and trailing spaces are ignored. All characters including '\0' are allowed */ --last; // '\0' for ( ; first < last && isspace(*first); ++first); // skip leading space for ( ; first < last && isspace(*last); --last); // skip trailing space for ( ; first < last; ++first, --last) if (*first != *last) return false; return true; } int palindromes(FILE *fp) { /** Print lines that are palindromes from the file. Return 0 if any line was selected, 1 otherwise; if any error occurs return 2 */ int ret = NO_MATCH; char *line = NULL; size_t line_size = 0; // line size including terminating '\0' if any ssize_t len = -1; // number of characters read, including '\n' if any, // . but not including the terminating '\0' while ((len = getline(&line, &line_size, fp)) != -1) { if (is_palindrome(line, line + len)) { if (printf("%s", line) < 0) { ret = ERROR; break; } else ret = MATCH; } } if (line) free(line); else ret = ERROR; if (!feof(fp)) ret = ERROR; return ret; } int main(int argc, char* argv[]) { int exit_code = NO_MATCH; if (argc == 1) // no input file; read stdin exit_code = palindromes(stdin); else { // process each input file FILE *fp = NULL; int ret = 0; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-") == 0) ret = palindromes(stdin); else if ((fp = fopen(argv[i], "r")) != NULL) { ret = palindromes(fp); fclose(fp); } else { fprintf(stderr, "%s: %s: could not open: %s\n", argv[0], argv[i], strerror(errno)); exit_code = ERROR; } if (ret == ERROR) { fprintf(stderr, "%s: %s: error: %s\n", argv[0], argv[i], strerror(errno)); exit_code = ERROR; } else if (ret == MATCH && exit_code != ERROR) // return MATCH if at least one line is a MATCH, propogate error exit_code = MATCH; } } return exit_code; }
The output state is 0 if any row is selected, 1 otherwise; if any error occurs, the exit status is 2. It uses GNU getline() , which allows arbitrary large lines to enter data.