1

For example, say I have a program like this:

file1.c is

#include <stdio.h>

int main(int argc, char **argv) {
    if (argc != 2) {
         printf("one file only\n");
         return (1);
     } else {
         for (size_t i = 0; argv[1][i] != '\0'; i++) {
             if(argv[1][i] != 'a') {
                 putchar(argv[1][i]);
             }
         }
         putchar('\n');
     }
 }

Above is a simple problem that iterates the input of argv[1] and removes every 'a'.

For example

$ gcc -Wall file1.c
$ ./a.out abcd
bcd

Is it possible to tweak this code to make piping work? As in,

$ echo abcd | ./a.out
bcd

1 Answers1

3

Is it possible to tweak this code to make piping work? As in,

Of course.

Instead of reading the contents of argv, you will need to read the data from stdin and process it as you see fit.

int main() {
   int c;
   while ( (c = getchar()) != EOF )
   {
      if(c != 'a') {
         putchar(c);
      }
   }
}

If you want to have both options available to you, you can use:

int main() {
   int c;
   if ( argc == 2 )
   {
      for (size_t i = 0; argv[1][i] != '\0'; i++) {
         if(argv[1][i] != 'a') {
            putchar(argv[1][i]);
         }
      }
   }
   else
   {
      int c;
      while ( (c = getchar()) != EOF )
      {
         if(c != 'a') {
            putchar(c);
         }
      }
   }

}

If you want the code unchanged, you will have to use another helper program that converts the output of echo abcd to become the arguments to a.out. On Linux, xargs is such a program.

echo abcd | xargs a.out
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • this version could be put into the `if (argc != 2)` block of the original code to support both modes of execution, although would probably be better in that case to check `if (argc < 2)` and maybe confirm stdin is not a terminal with `isatty`. – avigil Feb 25 '18 at 07:15