N08
N08

Reputation: 1315

Redirect two separate stdin as input to a program

The following example outputs the input that comes from stdin:

#include <iostream>

int main(int argc, char **argv)
{
    std::string s1, s2;
    while (getline(std::cin, s1))
    {
        std::cout << s1 << " 1\n";
    }

    while (getline(std::cin, s2))
    {
        std::cout << s2 << "2\n";
    }
    return 0;
}

I run the program like this: cat main.cpp | ./main which outputs

#include <iostream> 1
 1
int main(int argc, char **argv) 1
{ 1
 1
    std::string s1, s2; 1
    while (getline(std::cin, s1)) 1
    { 1
        std::cout << s1 << " 1\n"; 1
    } 1
         1
    while (getline(std::cin, s2)) 1
    { 1
        std::cout << s2 << "2\n"; 1
    } 1
} 1

Is there a way to pipe two separate inputs to a program through stdin? I.e., so if I write something like cat main.cpp cat main.cpp | ./main, then the first input gets assigned to s1 and the second to s2?

Upvotes: 2

Views: 214

Answers (2)

Barmar
Barmar

Reputation: 780723

cat doesn't put any kind of separator between the files, so there's no way for the program on the other side of the pipe to know where one file ends and the next one begins. You could do it yourself, with something like:

{ cat main.cpp; echo "**END**"; cat main.cpp; } | ./main

and change the program to look for the END line:

while (getline(std::cin, s1) && s1 != "**END**")
{
    std::cout << s1 << " 1\n";
}

Upvotes: 1

muXXmit2X
muXXmit2X

Reputation: 2765

AFAIK this is not possible, but you can simply use two files containing your input, pass them as a command line argument and read from them.

#include <iostream>
#include <fstream>

int main(int argc, char **argv)
{
    if (argc != 3) 
      return -1;

    std::ifstream ifs1(argv[1]);
    std::ifstream ifs2(argv[2]);

    if (!ifs1.is_open() || !ifs2.is_open())
      return -2;

    std::string s1, s2;
    while (getline(ifs1, s1))
    {
      std::cout << s1 << " 1\n";
    }

    while (getline(ifs2, s2))
    {
      std::cout << s2 << "2\n";
    }
    return 0;
}

And call it like this:

./main main.cpp main.cpp

You can even make this more flexible, allowing you to read as many files as you wish:

#include <iostream>
#include <fstream>

int main(int argc, char **argv)
{
    if (argc == 1) 
      return -1; // no input file given

    for (int i = 1; i < argc; ++i) { 
      std::ifstream ifs(argv[i]);

      if (!ifs.is_open()) {
        std::cout << argv[i] << ":file not found\n";
        continue;
      }

      std::string line;
      while (getline(ifs, line))
      {
        std::cout << line << " " << i << "\n";
      }
    }
}

Upvotes: 4

Related Questions