C++/exe

Advertisement


Question
Dear Ralph,

How are you? I was wondering if I could bother you with the following question:

There is a compiled command line program (available for both Windows and Linux: http://www.fourmilab.ch/random/) that I execute like this:

"ent.exe -b -t input.txt"

Here the file "input.txt" is simply a text file containing 1's and 0's, one value per line.

Now I'd like to run this program from within my C++ code. I know there is "system" command that could be used like this:
system("ent.exe -b -t input.txt"). However, the tricky part is reading the ent program's output so that my own program could continue using it. I'd like to read it into a string that I could then parse. This is the part that I don't know. I'd be very thankful if you could help me with this a little bit.

If you have time, maybe you could also comment on how the same works on Linux. What replaces the "system" command in Linux?

Regards,
Andres

Answer
Well the most obvious method would be to redirect the output to a file in the command line passed to system then after system returns open the file and read the contents into a string. As I do not have the ent program - nor wish to install it at this time - I used the common echo command as an example:

   #include <iostream> // for std::cout
   #include <fstream>  // for std::ifstream
   #include <string>   // for std::string
   #include <cstdlib>  // for std::system (or, if using C naming, just system)

   int main()
   {
       std::system("echo Hello > test.txt");  // Note use of > to redirect output to a file
       std::ifstream fin("test.txt");
       std::string echoed_text;
       std::getline(fin, echoed_text );
       std::cout << "Echoed text: '" << echoed_text << "'\n";
   }

Note the code is for _example_ purposes _only_ to show the idea and contains absolutely _no_ error checking and handling which of course you should add to any real-use code.

Note that the test.txt file is left hanging around, so you may wish to also add code to clean it up.

Another approach is to not run the ent program from your program but to allow your program to accept the ent output as input from stdin (std::cin in C++ IOStream terms), then pipe the output of ent into your program:

   ent.exe -b -t input.txt | andres-processor

This has the advantage that you can test your program from the command line by directly entering input from the keyboard or by redirecting test input from a file (or many files, one per run, each testing a specific input case).

If you wish to have a single command wrap the two command pipe commandline into a shell script (Linux) or batch / command  file (Windows).

Other solutions start to become more complex and usually platform specific (i.e. different for Windows and Linux). One way for Linux / Unix / Posix is to use a pipe in your program, for an example see:

   http://www.dreamincode.net/forums/topic/72812-redirect-system-calls/

(note: I did not try this).

While popen/pclose are not available as either standard C/C++ library functions nor are part of the Windows APIs the Microsoft Visual C++ runtime library contains _popen and _pclose which can be used in a similar way - see:

   http://msdn.microsoft.com/en-us/library/96ayss4b(v=vs.80).aspx

for a similar, C-only, MSVC++ example.

I re-worked my original example to use _popen and _pclose under MSVC++ 2010:

   #include <iostream> // for std::cout, std::cerr
   #include <stdio.h>  // for FILE, fgets and non-standard _popen and _pclose

   int main()
   {
       FILE * fpipe;
       if ( (fpipe=_popen("echo Hello", "rt")) == NULL )
       {
         std::cerr << "Failed to open pipe for command.\n";
         return 1;
       }
       size_t const BufSize(128);
       char buffer[BufSize];
       std::cout << "Echoed text: '";
       while ( fgets(buffer, BufSize, fpipe) )
       {
         std::cout << buffer;
       }
       std::cout << "'\n";
       _pclose( fpipe );
   }
  
Note that I did add some error checking but not quite as much as in the MSDN example. Also note that this version dumps the end of line generated by the echo command into the buffer which the original did not.

You can remove the difference in the names of the Microsoft and  Posix (Linux, Unix) names (i.e. the MS leading underscore in the function names) by writing wrapper inline functions that simply forward to the MS runtime library functions:

   inline FILE *popen(const char *command, const char *mode)
   {
       return _popen(command, mode);
   }

   inline int pclose(FILE *stream)
   {
       return _pclose(stream);
   }

However, these should _only_ be defined when building for the Microsoft compiler and runtime library or a compiler/runtime library that also implements the Microsoft _popen and _pclose functions and not the Linux style popen/pclose functions. This can be done using pre-processor directives and compiler pre-defined macros. The MSVC++ compiler identification macro is called _MSC_VER - see:

   http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx

for more details.

Hence we can do something like so:

   #ifdef _MSC_VER
   # if _MSC_VER >= 1300
   inline FILE *popen(const char *command, const char *mode)
   {
       return _popen(command, mode);
   }

   inline int pclose(FILE *stream)
   {
       return _pclose(stream);
   }
   # else
   #  error MSVC++ .NET 2003 or later required.
   # endif
   #endif

Note the test for _MSC_VER being at least 1300, which should represent MSVC++ .NET 2003, the earliest version _popen/_pclose have MSDN documentation listed for (which may mean they are present in earlier editions of MSVC++ but MSDN no longer bothers to keep the documentation available for them!). We might find that earlier versions also included the functions with names without the underscore making the forwarding functions unnecessary. Hence the 1300 value may need to be tweaked!

There are other non C/C++ standard ways to achieve this, however I hope the above gives you enough to work with.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.