Supporting Piping (A Useful Hello World)

Posted by blastthisinferno on Stack Overflow See other posts from Stack Overflow or by blastthisinferno
Published on 2010-12-27T23:18:07Z Indexed on 2010/12/27 23:54 UTC
Read the original article Hit count: 264

I am trying to write a collection of simple C++ programs that follow the basic Unix philosophy by:

  1. Make each program do one thing well.
  2. Expect the output of every program to become the input to another, as yet unknown, program.

I'm having an issue trying to get the output of one to be the input of the other, and getting the output of one be the input of a separate instance of itself. Very briefly, I have a program add which takes arguments and spits out the summation. I want to be able to pipe the output to another add instance.

./add 1 2 | ./add 3 4

That should yield 6 but currently yields 10.

I've encountered two problems:

  1. The cin waits for user input from the console. I don't want this, and haven't been able to find a simple example showing a the use of standard input stream without querying the user in the console. If someone knows of an example please let me know.
  2. I can't figure out how to use standard input while supporting piping. Currently, it appears it does not work. If I issue the command ./add 1 2 | ./add 3 4 it results in 7.

The relevant code is below:

add.cpp snippet

// ... COMMAND LINE PROCESSING ...
    std::vector<double> numbers = multi.getValue(); // using TCLAP for command line parsing

    if (numbers.size() > 0)
    {
    double sum = numbers[0];

    double arg;
    for (int i=1; i < numbers.size(); i++)
    {
      arg = numbers[i];

      sum += arg;
    }

    std::cout << sum << std::endl;
  }
  else
  {
      double input;
      // right now this is test code while I try and get standard input streaming working as expected
      while (std::cin)
      {
            std::cin >> input;

            std::cout << input << std::endl;
      }

    }
// ... MORE IRRELEVANT CODE ...

So, I guess my question(s) is does anyone see what is incorrect with this code in order to support piping standard input? Are there some well known (or hidden) resources that explain clearly how to implement an example application supporting the basic Unix philosophy?

@Chris Lutz I've changed the code to what's below. The problem where cin still waits for user input on the console, and doesn't just take from the standard input passed from the pipe. Am I missing something trivial for handling this? I haven't tried Greg Hewgill's answer yet, but don't see how that would help since the issue is still with cin.

// ... COMMAND LINE PROCESSING ...
    std::vector<double> numbers = multi.getValue(); // using TCLAP for command line parsing

    double sum = numbers[0];

    double arg;
    for (int i=1; i < numbers.size(); i++)
    {
      arg = numbers[i];

      sum += arg;
    }

    // right now this is test code while I try and get standard input streaming working as expected
    while (std::cin)
    {
          std::cin >> arg;

          std::cout << arg << std::endl;
    }

    std::cout << sum << std::endl;
// ... MORE IRRELEVANT CODE ...

© Stack Overflow or respective owner

Related posts about c++

Related posts about command-line