How to Parse Command Line Arguments in C++? [dupli

2019-01-03 19:30发布

Possible Duplicate:
What parameter parser libraries are there for C++?

What is the best way of parsing command-line arguments in C++ if the program is specified to be run like this:

prog [-abc] [input [output]]

Is there a library in STL to do this?


Related:

10条回答
Bombasti
2楼-- · 2019-01-03 19:42
for (int i = 1; i < argc; i++) {

    if (strcmp(argv[i],"-i")==0) {
        filename = argv[i+1];
        printf("filename: %s",filename);
    } else if (strcmp(argv[i],"-c")==0) {
        convergence = atoi(argv[i + 1]);
        printf("\nconvergence: %d",convergence);
    } else if (strcmp(argv[i],"-a")==0) {
        accuracy = atoi(argv[i + 1]);
        printf("\naccuracy:%d",accuracy);
    } else if (strcmp(argv[i],"-t")==0) {
        targetBitRate = atof(argv[i + 1]);
        printf("\ntargetBitRate:%f",targetBitRate);
    } else if (strcmp(argv[i],"-f")==0) {
        frameRate = atoi(argv[i + 1]);
        printf("\nframeRate:%d",frameRate);
    }

}
查看更多
Viruses.
3楼-- · 2019-01-03 19:46

You can use GNU GetOpt (LGPL) or one of the various C++ ports, such as getoptpp (GPL).

A simple example using GetOpt of what you want (prog [-ab] input) is the following:

// C Libraries:
#include <string>
#include <iostream>
#include <unistd.h>

// Namespaces:
using namespace std;

int main(int argc, char** argv) {
    int opt;
    string input = "";
    bool flagA = false;
    bool flagB = false;

    // Retrieve the (non-option) argument:
    if ( (argc <= 1) || (argv[argc-1] == NULL) || (argv[argc-1][0] == '-') ) {  // there is NO input...
        cerr << "No argument provided!" << endl;
        //return 1;
    }
    else {  // there is an input...
        input = argv[argc-1];
    }

    // Debug:
    cout << "input = " << input << endl;

    // Shut GetOpt error messages down (return '?'): 
    opterr = 0;

    // Retrieve the options:
    while ( (opt = getopt(argc, argv, "ab")) != -1 ) {  // for each option...
        switch ( opt ) {
            case 'a':
                    flagA = true;
                break;
            case 'b':
                    flagB = true;
                break;
            case '?':  // unknown option...
                    cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
                break;
        }
    }

    // Debug:
    cout << "flagA = " << flagA << endl;
    cout << "flagB = " << flagB << endl;

    return 0;
}
查看更多
4楼-- · 2019-01-03 19:54

The suggestions for boost::program_options and GNU getopt are good ones.

However, for simple command line options I tend to use std::find

For example, to read the name of a file after a -f command line argument. You can also just detect if a single-word option has been passed in like -h for help.

#include <algorithm>

char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
    char ** itr = std::find(begin, end, option);
    if (itr != end && ++itr != end)
    {
        return *itr;
    }
    return 0;
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
    return std::find(begin, end, option) != end;
}

int main(int argc, char * argv[])
{
    if(cmdOptionExists(argv, argv+argc, "-h"))
    {
        // Do stuff
    }

    char * filename = getCmdOption(argv, argv + argc, "-f");

    if (filename)
    {
        // Do interesting things
        // ...
    }

    return 0;
}

On thing to look out for with this approach you must use std::strings as the value for std::find otherwise the equality check is performed on the pointer values.


I hope it is okay to edit this response instead adding a new one, as this is based on the original answer. I re-wrote the functions slightly and encapsulated them in a class, so here is the code. I thought it might be practical to use it that way as well:

class InputParser{
    public:
        InputParser (int &argc, char **argv){
            for (int i=1; i < argc; ++i)
                this->tokens.push_back(std::string(argv[i]));
        }
        /// @author iain
        const std::string& getCmdOption(const std::string &option) const{
            std::vector<std::string>::const_iterator itr;
            itr =  std::find(this->tokens.begin(), this->tokens.end(), option);
            if (itr != this->tokens.end() && ++itr != this->tokens.end()){
                return *itr;
            }
            static const std::string empty_string("");
            return empty_string;
        }
        /// @author iain
        bool cmdOptionExists(const std::string &option) const{
            return std::find(this->tokens.begin(), this->tokens.end(), option)
                   != this->tokens.end();
        }
    private:
        std::vector <std::string> tokens;
};

int main(int argc, char **argv){
    InputParser input(argc, argv);
    if(input.cmdOptionExists("-h")){
        // Do stuff
    }
    const std::string &filename = input.getCmdOption("-f");
    if (!filename.empty()){
        // Do interesting things ...
    }
    return 0;
}
查看更多
一纸荒年 Trace。
5楼-- · 2019-01-03 19:56

Yet another alternative is The Lean Mean C++ Option Parser:

http://optionparser.sourceforge.net

It is a header-only library (just a single header file, in fact) and unlike all the other suggestions it is also freestanding, i.e. it has no dependencies whatsoever. In particular there's no dependency on the STL. It does not even use exceptions or anything else that requires library support. This means it can be linked with plain C or other languages without introducing "foreign" libraries.

Like boost::program_options its API offers convenient direct access to options, i.e. you can write code like this

if (options[HELP]) ... ;

and

int verbosity = options[VERBOSE].count();

Unlike boost::program_options however this is simply using an array indexed with a (user-provided) enum. This offers the convenience of an associative container without the weight.

It's well documented and has a company-friendly license (MIT).

TLMC++OP includes a nice formatter for usage messages that can do line-wrapping and column alignment which is useful if you're localizing your program, because it ensures that the output will look good even in languages that have longer messages. It also saves you the nuisance of manually formatting your usage for 80 columns.

查看更多
叛逆
6楼-- · 2019-01-03 19:59

Try CLPP library. It's simple and flexible library for command line parameters parsing. Header-only and cross-platform. Uses ISO C++ and Boost C++ libraries only. IMHO it is easier than Boost.Program_options.

Library: http://sourceforge.net/projects/clp-parser

26 October 2010 - new release 2.0rc. Many bugs fixed, full refactoring of the source code, documentation, examples and comments have been corrected.

查看更多
爷、活的狠高调
7楼-- · 2019-01-03 20:02

Boost.Program_options should do the trick

查看更多
登录 后发表回答