What is it?
I/O Redirection is a powerful tool that allows the shell to either simulate keyboard input from a file (input redirection), capture all output in a file (output redirection), or both. Using redirection allows programs to use files for input and output using only cin
, cout
, and/or cerr
, eliminating the need to explicitly handle files (fopen()
) or input streams (istream
or ostream
).
Examples
% ./program < redirected-to-cin.txt
% ./program > redirected-from-cout.txt
% ./program > redirected-from-cout.txt 2> redirected-from-cerr.txt
% ./program < redirected-to-cin.txt > redirected-from-cout.txt
etc...
How to do it
Command-line Arguments (options, arguments and filenames)
To specify command-line arguments in Xcode select from the menu Product -> Scheme -> Edit Scheme. Savvy users will use the keyboard shortcut Command+<. The arguments specified this way will be read and passed to your program in argv[]
, which will allow you use getopt()
, getopt_long()
, or simply parse the arguments manually.
File Redirection
Xcode will allow you specify command-line parameters, but no longer directly supports command-line style redirection. To provide your own support, you can use freopen()
. This will let you open a file using a filename and associate it with a stream.
Examples
int main() {
freopen("redirected-to-cin.txt", "r", stdin); // Redirected input
freopen("redirected-from-cout.txt", "w", stdout); // Redirected output
freopen("redirected-from-cerr.txt", "w", stderr); // Redirected output
return 0;
}
How to do it well
Conditional compilation
You have seen compiler guards before in header files in the form of
#ifndef VAR
#define VAR
...
#endif
You can read more about these here. On macOS, the operating system macro is __APPLE__
.
#ifdef __APPLE__
freopen("inputFilename.txt", "r", stdin);
freopen("outputFilename.txt", "w", stdout);
#endif
This will compile with freopen()
only when the operating system is macOS, so when your code compiles on CAEN or the Autograder, these lines are ignored.
How to do it with style
Using environment variables and testing for unopened files
Another solution is to #include <stdlib.h>
(this is important!) and use getenv()
, which lives in stdlib.h. This will allow you to change your redirected
files from the "Edit Scheme" dialog, without needing to edit your source code directly.
#ifdef __APPLE__
if (getenv("STDIN")) {
if (!freopen(getenv("STDIN"), "r", stdin)) {
cerr << "Unable to redirect stdin to " << getenv("STDIN") << endl;
exit (1);
}
}
if (getenv("STDOUT")) {
if (!freopen(getenv("STDOUT"), "w", stdout)) {
cerr << "Unable to redirect stdout to " << getenv("STDOUT") << endl;
exit (1);
}
}
if (getenv("STDERR")) {
if (!freopen(getenv("STDERR"), "w", stderr)) {
cerr << "Unable to redirect stderr to " << getenv("STDERR") << endl;
exit (1);
}
}
#endif