1

I want to redirect cout to a file when needed. Here is the main part of my test program, but I can't figure out some input was not directed to the file.

     ucla();
     ucla() { 
        std::cout << "inside ucla" << std::endl;
      }

     int main() {
           const char* outName = argv[2];                                                                                          
           std::string outFile(outName);                                                                                                                                                                                                                   
           std::streambuf *coutbuf, *termbuf;                                                                                      
           termbuf = std::cout.rdbuf();                                                                                                                                                                                                                    
           if (!outFile.empty()) {                                                                                                         
                 std::ofstream outstr;                                                                                                   
                 outstr.open(argv[2]);                                                                                                   
                 coutbuf = outstr.rdbuf();                                                                                               
                 std::cout.rdbuf(coutbuf);                                                                                               
                 std::cout << "here" << std::endl;                                                                               
           } else {std::cout.rdbuf(termbuf);}                                                                                                                                                                                                              
           std::cout << "this file " << std::endl;  

          ucla();
          }

When the program is run, only here was written to the file, I expect this file inside ucla I searched earlier threads, and I can't figure out what is missing. Thanks

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
findanswer
  • 35
  • 5

1 Answers1

0

Your program has undefined behavior.

coutbuf is destructed when outstr is destructed. Since you didn't reset the rdbuf of cout when the if-block ended, cout points to a dangling rdbuf outside the if-block.


Suggestion for cleanup. Always provide a return type for functions. Instead of

ucla();

use

void ucla();

Update, in response to OP's comment

To resolve the problem, it will be good to move all the "application code" to another function and call that function from main. Leave the rdbuf handling code in main.

void ucla()
{
   std::cout << "inside ucla" << std::endl;
}

void application_main()
{
   std::cout << "here" << std::endl;
   std::cout << "this file " << std::endl;
   ucla();
}

int main()
{
   const char* outName = argv[2];
   std::string outFile(outName);

   // Save the rdbuf of cout.
   std::streambuf* coutbuf = std::cout.rdbuf();

   termbuf = std::cout.rdbuf();
   if (!outFile.empty())
   {
      std::ofstream outstr;
      outstr.open(argv[2]);
      std::cout.rdbuf(outstr.rdbuf());

      // Needs to be here so that every use of cout will redirect the output
      // to the file.
      application_main();
   }
   else
   {
      // In this branch, use of cout will produce output in the console.
      application_main();
   }

   // Restore the rdbuf of cout.
   std::cout.rdbuf(coutbuf);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Any suggestion one what I can do? I need to be able to send the output to the output file if it were not empty, I be able to send the cout to the file, otherwise, it will be just cout. – findanswer Feb 15 '19 at 06:12
  • Better: have `application_main()` take a `std::ostream&` argument and then call it with `std::cout` or an opened `std::ofstream` depending. – Shawn Feb 15 '19 at 06:40
  • @Shawn, Your suggestion will definitely be a better option if the application is as simple as the posted cod. iI there are other functions in the same file or functions in other files, you can't freely use `cout` and get the output redirected to a file. You'll have to pass the `ostream` object to every downstream function and use it instead of using `cout`. That would be tedious, I think. – R Sahu Feb 15 '19 at 06:52