Note that there are some explanatory texts on larger screens.

plurals
  1. POSupporting Piping (A Useful Hello World)
    primarykey
    data
    text
    <p>I am trying to write a collection of simple C++ programs that follow the basic Unix philosophy by:</p> <ol> <li>Make each program do one thing well.</li> <li>Expect the output of every program to become the input to another, as yet unknown, program.</li> </ol> <p>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 <strong>add</strong> which takes arguments and spits out the summation. I want to be able to pipe the output to another <strong>add</strong> instance.</p> <pre><code>./add 1 2 | ./add 3 4 </code></pre> <p>That <em>should</em> yield <strong><em>10</em></strong> but currently yields <strong><em>7</em></strong>.</p> <p>I've encountered two problems:</p> <ol> <li>The <em>cin</em> 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.</li> <li>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 <strong><em>./add 1 2 | ./add 3 4</em></strong> it results in 7.</li> </ol> <p>The relevant code is below:</p> <p><strong>add.cpp snippet</strong></p> <pre><code>// ... COMMAND LINE PROCESSING ... std::vector&lt;double&gt; numbers = multi.getValue(); // using TCLAP for command line parsing if (numbers.size() &gt; 0) { double sum = numbers[0]; double arg; for (int i=1; i &lt; numbers.size(); i++) { arg = numbers[i]; sum += arg; } std::cout &lt;&lt; sum &lt;&lt; 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 &gt;&gt; input; std::cout &lt;&lt; input &lt;&lt; std::endl; } } // ... MORE IRRELEVANT CODE ... </code></pre> <p>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 <a href="http://www.faqs.org/docs/artu/ch01s06.html" rel="nofollow">basic Unix philosophy</a>?</p> <p><em><strong>@Chris Lutz</em></strong> I've changed the code to what's below. The problem where <em>cin</em> 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 <em>cin</em>.</p> <pre><code>// ... COMMAND LINE PROCESSING ... std::vector&lt;double&gt; numbers = multi.getValue(); // using TCLAP for command line parsing double sum = numbers[0]; double arg; for (int i=1; i &lt; 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 &gt;&gt; arg; std::cout &lt;&lt; arg &lt;&lt; std::endl; } std::cout &lt;&lt; sum &lt;&lt; std::endl; // ... MORE IRRELEVANT CODE ... </code></pre> <p><strong>EDIT:</strong> Almost there, this allows the output to be piped to the input, however it appears it's piping a duplicate. I'm issuing <strong><em>./add 1 2 | ./add 3 4</em></strong> and getting <strong><em>13</em></strong>. With some extra <em>cout</em> statements in the while loop, I can see two values of <strong><em>3</em></strong> coming from <em>cin</em> when I only have one <em>cout</em> statement. Why am I getting a duplicate?</p> <pre><code>// ... COMMAND LINE PROCESSING ... std::vector&lt;double&gt; numbers = multi.getValue(); // using TCLAP for command line parsing double sum = numbers[0]; double arg; for (int i=1; i &lt; numbers.size(); i++) { arg = numbers[i]; sum += arg; } if (!isatty(fileno(stdin))) { while (std::cin) { std::cin &gt;&gt; arg; // this may require the use of std::strtod(), but to simplify the example I'm keeping it as this. sum += arg; } } std::cout &lt;&lt; sum &lt;&lt; std::endl; // ... MORE IRRELEVANT CODE ... </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload