Search code examples
c++command-line-argumentsstdinargv

Design pattern for accepting stdin OR CLI arguments


For C++, how do I accept CLI arguments or stdin?

For instance, let's say I have a function foo() that I want to call over a variable number of arguments. For standard args, I simply use something like:

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cout << "usage goes here.\n";
    } else {
        for (int i; i < argc; ++i) {
            foo(argv[i]);
        }
    }
}

But what if they sent them to me via stdin and piped the parameters to my application? Is there a way to detect and accept/handle both? What is an efficient design pattern to do this in modern C++ (C++11 and beyond)?

I'm interested in the design pattern / sample implementation. Feel free to reference a library that does this (Boost?) but please share/explain an example implementation.


Solution

  • Normally you would only read input from stdin, not arguments/options. By reading and evaluating arguments/options, the program should decide if it expects input from stdin or e.g. a file argument.

    As example from the manpage of grep:

    Synopsis

    grep [OPTIONS] PATTERN [FILE...]

    Description

    grep searches the named input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN.

    A lack of the FILE argument or the - option indicates grep to read stdin.

    Invokation of your program could look like this, the lack of the file argument indicates reading input from stdin:

    # file argument, input is in the file
    command -o someoption filename
    
    # file content supplied via stdin
    command -o someoption < filename     
    
    # with pipe and - (stdin) as file argument
    othercommand | command -o someoption -
    

    For parsing options/arguments boost has the program options library