0
#include <cstddef>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;


int main() {
   
    //read the lines from the piped file using cin
    string response;
    int i = 0;
    while (getline(cin, response)) {
        //if the response is empty, stop
        if (response.empty()) {
            break;
        }
        
        //Write each odd line (1,3, etc..) to stderr (cerr) 
        //Write each even line (2,4. etc..) to stdout (cout) 
        if (i % 2 != 1) { //send odd to stderr
            cerr << "err: " << response << endl;
        }
        else { //send even to stdout
            cout << "out: " << response << endl;
        }
        i++;

    }

        
    return 0;
}

I want to redirect stderr to /dev/null, how would I go about doing so? I'm new to C++ and trying to learn by practicing, however, I'm not easily able to find an answer that fits my existing program.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Do you need to redirect it from within the program? Typically you just use it, and the caller can run with `2>/dev/null` to discard it if they want to. – ShadowRanger Apr 16 '22 at 02:29
  • Yes, I would like to do it from within the program, not from the command line. I understand how to do it from the command line already. – Guru Gossip Apr 16 '22 at 02:42
  • 2
    In that case, check `man dup2`, and use it to replace file descriptor 2 (the fd for stderr). – ShadowRanger Apr 16 '22 at 02:48

1 Answers1

1

Besides the excellent commentary above, it is pretty easy to make a “null” streambuf sink in C++.

#include <iostream>

struct null_streambuf: public std::streambuf
{
  using int_type = std::streambuf::int_type;
  using traits   = std::streambuf::traits_type;

  virtual int_type overflow( int_type value ) override
  {
    return value;
  }
};

To use it, just set the rdbuf:

int main()
{
  std::cerr.rdbuf( new null_streambuf );
  std::cerr << "Does not print!\n";
}

If you wish to be able to turn it off and on, you will have to remember the original and restore it, not forgetting to delete the new null_streambuf.

int main()
{
  std::cerr << "Prints!\n";

  auto original_cerr_streambuf = std::cerr.rdbuf( new null_streambuf );
  std::cerr << "Does not print.\n";

  delete std::cerr.rdbuf( original_cerr_streambuf );
  std::cerr << "Prints again!\n";
}

This does have the objective effect of being compiled to code, which I suspect is the advantage you are looking for: the ability to dynamically enable and disable diagnostic output.

This is, however, the usual function of a debug build, where you use the DEBUG macro to decide whether or not to compile something (such as error output operations) into the final executable.

Keep in mind that this does not disable output on standard error via other means, but only through cerr.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • Is it possible to do without the struct ? Just curious, otherwise, I think this is a very well thought out answer and seems to fit my needs. Thank you for the input! – Guru Gossip Apr 16 '22 at 03:27
  • I think just `std::cerr.rdbuf(nullptr);` is permitted and will have mostly the same effect. – aschepler Apr 16 '22 at 04:11
  • [Yes, but doing so sets badbit, and efforts to endrun around this may invoke UB.](https://stackoverflow.com/questions/25690636/is-it-valid-to-construct-an-stdostream-from-a-null-buffer). Whether that is an actual issue or not IDK, but I prefer not to poke the bear. – Dúthomhas Apr 16 '22 at 04:15
  • @Dúthomhas that link says `badbit` is set if `ostream` is *constructed* with a `nullptr`, but it doesn't say anything about what happens if `nullptr` is passed to `rdbuf()` after construction. Neither does [this page](https://en.cppreference.com/w/cpp/io/basic_ios/rdbuf), but it does say that an `ostream` can have "no associated stream buffer", so there has to be a valid way for `nullptr` to be used, without putting the stream into an error state. – Remy Lebeau Apr 16 '22 at 04:22
  • @aschepler - Thanks, that's even easier, plain and simple. You should submit an answer and I'll accept it as a solution. :) – Guru Gossip Apr 16 '22 at 04:54