1

This is what I tried:

#include <iostream>
#include <string>

int main(int argc, char const *argv[]) {
  using namespace std;
  for (string cin_line; getline(cin, cin_line);) {
    cout << cin_line << endl;
  }
  FILE* pipe = popen("app.exe", "r");
  for (string result_line; getline(pipe, result_line);) {
    cout << result_line << endl;
  }
  pclose(pipe);
  return 0;
}

It doesn't compile, the result is:
no matching function for call to 'getline(FILE*&, std::__cxx11::string&)'

Second example I've found here: https://stackoverflow.com/a/10702464/393087 But it seems mingw doesn't have pstream included: fatal error: pstream.h: No such file or directory - edit: ok I know, I missed that this is not a GCC library, it is named like it was but this is separate download: http://pstreams.sourceforge.net/

I know how to do it using buffer and get whole output on single line (like here: https://stackoverflow.com/a/478960/393087 ) then explode the line by \n and get my array, but the point here is that I must provide the output as soon as the input comes in.

Also I tried example from here: https://stackoverflow.com/a/313382/393087 - I've added main function to that:

#include <cstdio>
#include <iostream>
#include <string>

int main(int argc, char const *argv[]) {
  using namespace std;
  FILE * fp ;

  if((fp= popen("/bin/df","r")) == NULL) {
      // error processing and exit
  }
  ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor

  string s;
  while (! ins.eof()){
      getline(ins,s);
      // do something
  }  
  return 0;
}

This also doesn't compile:
error: variable 'std::ifstream ins' has initializer but incomplete type ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor

Community
  • 1
  • 1
rsk82
  • 28,217
  • 50
  • 150
  • 240
  • 1
    You need `` – David G Apr 01 '15 at 14:04
  • [`std::getline`](http://en.cppreference.com/w/cpp/string/basic_string/getline) reads from C++ streams only. To read a line from an old C-file stream you need to use the C function [`fgets`](http://en.cppreference.com/w/cpp/io/c/fgets). – Some programmer dude Apr 01 '15 at 14:04
  • As for your second piece of code, don't do `while (!ins.eof())` as this will seldom work as expected, because the `eofbit` flag will not be set until *after* you try to read from beyond the end of the file, causing the loop to iterate once to many. Instead use `while (std::getline(...))`. – Some programmer dude Apr 01 '15 at 14:08
  • @0x499602D2: no, adding `` header doesn't remove the error. – rsk82 Apr 01 '15 at 14:45

1 Answers1

1

You can't do this:

FILE* pipe = popen("app.exe", "r");
for (string result_line; getline(pipe, result_line);) {
    cout << result_line << endl;
}
pclose(pipe);

You need to do this:

#include <boost/noncopyable.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

FILE* pipe = popen("app.exe", "r");

boost::iostreams::file_descriptor_source 
 source(fileno(pipe), boost::iostreams::never_close_handle);

boost::iostreams::stream<boost::iostreams::file_descriptor_source>
 stream(source, 0x1000, 0x1000); 

string result_line; 
while (getline(stream, result_line)) { 
    cout << result_line << endl;
}

:)

AntonioCS
  • 8,335
  • 18
  • 63
  • 92
Aymar Fisherman
  • 388
  • 1
  • 8
  • I've voted up, but the answer is not what I meant, it is for reading file from disk, but what I need is to run a command and output its results. – rsk82 Apr 01 '15 at 18:25
  • 1
    Haha, you're right, I missread the popen call... Then you can use Boost to accomplish that: `#include #include #include ... FILE* pipe = popen("app.exe", "r"); boost::iostreams::file_descriptor_source source(fileno(pipe), boost::iostreams::never_close_handle); boost::iostreams::stream stream(source, 0x1000, 0x1000); string filename; while (getline(stream, filename)) { ifstream file_stream(filename.c_str(), ifstream::in); .... } ` – Aymar Fisherman Apr 01 '15 at 18:41