My program needs to accept three kinds of input commands bel开发者_StackOverflow中文版ow:
./Myprogram input.txt
./Myprogram < input.txt
./Myprogram
I'm thinking about using argc
to check the number of arguments to resolve the first two situations (since redirection doesn't count as an argument). But then I stuck on the last case, which simply waits for an user input.
I'm wondering if there is a way to tell if a redirection is present in the shell command?
For a more complicated scenario such as a mix of redirection and argv forms (see below). Is there a way to do it or it's simply a bad design for taking user commands?
./Myprogram input1.txt input2.txt input3.txt
./Myprogram input1.txt < input2.txt input3.txt
./Myprogram
Any help will be much appreciated!
Z.Zen
Redirection will never be seen by your program as an argument. So in:
./Myprogram input.txt
./Myprogram < input.txt
./Myprogram
the second and third forms are identical. As for your second set of possibilities:
./Myprogram input1.txt input2.txt input3.txt
./Myprogram input1.txt < input2.txt input3.txt
./Myprogram
the second line is equivalent to:
./Myprogram input1.txt input3.txt < input2.txt
and it's also indistinguishable from:
./Myprogram input1.txt input3.txt
(the only different being where standard input actually comes from).
A typical way some programs handle mixed input from stdin and files specified on the command line is to accept "-"
as a special filename meaning "use stdin as the input file at this position in the argument list". Many such programs will default to processing a singleton-list of "-"
if the argument list is empty.
The basic algorithm is:
if (there are no arguments left after parsing options)
call_function(stdin);
else
{
foreach remaining argument
{
FILE *fp;
if (strcmp(argument, "-") == 0)
call_function(stdin);
else if ((fp = fopen(argument, "r")) == 0)
...error handling...
else
{
call_function(fp);
fclose(fp);
}
}
}
You could pass the file name to the 'call_function()' too, and sometimes I write the code with the output file stream specified. That function ('call_function()') is what processes one file - reading to the end of the file. It does not close the file; it was given an open file and should not close it.
The first 'if' deals with the I/O redirection case, of course.
I wrote, many years go, a function to handle this loop. It simplifies my life whenever I need to write a command in this 'UNIX filter' idiom - which is quite often. Along with a standardized error reporting package, it greatly simplifies life. Having it as a function also permits me to use variants on it, such as one that creates a backup of the file before it is overwritten, or which safely overwrites the file if the function completes successfully.
@R.. is correct for the usual cases.
If you want to have interactive behavior in case #3 but not #2, beyond letting the terminal buffer the user's input by line, you can use isatty
(specifically isatty(0)
) to determine whether there's a person on the other end.
This is not standard C, but neither is the notion of a terminal or a shell!
I'm wondering if there is a way to tell if a redirection is present in the shell command?
No. From your program's point of view there is no difference between these two cases:
./Myprogram < input.txt
./Myprogram
In both the cases the program is not taking any command line argument and would get it's input from the standard input.
In the first case it's the shell that is connecting the contents of the file input.txt
to the stdin
of your program your program knows nothing about this.
It is possible to tell whether there is data to read by using select() on stdin. This will not tell you whether there is a redirection (you won't be able to tell when the file is empty, or when for some reason the user managed to put something on stdin before your program got a chance to test for it). Whether it works for your case or not depends on what you want to do in borderline cases.
Alternatively, you can use isatty() on stdin to find out if it's a tty or not. It's what most programs will do to find out whether they are interactive or not, and probably better in your case.
Now, you may notice that blocking waiting for user input in the third case is what all standard tools do, and is probably the behavior most users expect of your program too.
精彩评论