views:

281

answers:

6

I'm running a program and redirecting cout to an outfile, like so:

./program < infile.in > outfile.o  

I want to be able to read in an option ('-h' or '--help') from the command line and output a help message to the terminal. Is there a way I can do this but still have the regular cout from the rest of the program go to the outfile?

Would cout be the right object to use for such a thing?

A: 

You should use cerr instead of cout. Using shell redirection > only redirects stdout (cout), not stderr (cerr).

KeithB
+1  A: 

You may like to output the help message to stderr. Stderr is generally used for non-normal output and you may consider a usage paragraph to be such output.

abc
+2  A: 

~$ cmd | tee log_file to dup stdout to file and terminal
~$ cmd 2>log_file to print stdout onto terminal and stderr into a file

Nikolai N Fetissov
+13  A: 

You should use cerr to output your help message to STDERR, which is not included in your redirection to outfile.o.

Given ./program < infile.in > outfile.o:

cout << "This writes to STDOUT, and gets redirected to outfile.";
cerr << "This doesn't get redirected, and displays on screen.";

If, later on, you want to redirect both STDOUT and STDERR, you can do

./program < infile.in &> outfile.o

If you want to redirect only STDERR, but allow STDOUT to display, use

./program < infile.in 2> outfile.o

Bash redirection is more complex than most people realize, and often everything except the simplest form (">") gets overlooked.

meagar
awesome, thanks for the help!
zebraman
+1  A: 

One of the things I've done - not saying this is always appropriate - is write modules that have something like this signature.

void write_out(ostream &o);

And then I can create fstream objects and pass them in, or pass in cout and cerr, whatever I need to at that time. This can be helpful in writing logging code where sometimes you want to see on-terminal what happens, and at other times you just want a logfile.

HTH.

Paul Nathan
+1  A: 

If you're on linux you can use the pseudo device /dev/tty to output to a controlling terminal (if any). This will work even if stderr is redirected as well as stdout. Other operating systems may provide similar mechanisms.

E.g.

#include <iostream>
#include <ostream>
#include <fstream>

int main()
{
        std::ofstream term("/dev/tty", std::ios_base::out);

        term << "This goes to terminal\n";
        std::cout << "This goes to stdout\n";

        return 0;
}

Will work like this:

$ ./a.out
This goes to stdout
This goes to terminal
$ ./a.out >/dev/null
This goes to terminal

Note the way that the with the two streams being buffered independently the relative ordering if they are outputting to the same device is not necessarily preserved. This can be adjusted by flushing the streams at appropriate times.

Charles Bailey