Hvordan analysere kommandolinjeargumenter i C ++?

stemmer
158

Mulig Duplicate:
Hva parameter parser bibliotekene er der for C ++?

Hva er den beste måten å parsing kommandolinjeargumenter i C ++ hvis programmet er spesifisert til å kjøres som dette:

prog [-abc] [input [output]]

Er det et bibliotek i STL å gjøre dette?


I slekt:

Publisert på 14/05/2009 klokken 20:46
kilden bruker
På andre språk...                            


10 svar

stemmer
78

Boost.Program_options bør gjøre triks

Svarte 14/05/2009 kl. 20:49
kilden bruker

stemmer
30

Du kan bruke GNU getopt (LGPL) eller en av de ulike C ++ porter, slik som getoptpp (GPL).

Et enkelt eksempel ved hjelp av getopt om hva du vil ( prog [-ab] inngang ) er følgende:

// 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;
}
Svarte 14/05/2009 kl. 20:49
kilden bruker

stemmer
3

Jeg vil anbefale boost :: program_options hvis du kan bruke Boost lib.

Det er ingenting konkret i STL heller ikke i den vanlige C ++ / C runtime libs.

Svarte 14/05/2009 kl. 20:50
kilden bruker

stemmer
193

Forslagene til boost::program_optionsog GNU getopt er gode.

Men for enkle kommandolinjevalg jeg pleier å bruke std :: finne

For eksempel å lese navnet på en fil etter en -fkommandolinje argument. Du kan også bare oppdage om et enkelt ord alternativ har gått inn som -hfor å få hjelp.

#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;
}

På ting å se opp for med denne tilnærmingen må du bruke std :: strenger som verdien for std :: finne ellers likestilling kontrollen utføres på pekeren verdier.


Jeg håper det er greit å redigere dette svaret i stedet legge til en ny en, da dette er basert på den opprinnelige svaret. Jeg re-skrev funksjonene litt og innkapslet dem i en klasse, så her er koden. Jeg tenkte at det kunne være praktisk å bruke det på den måten også:

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;
}
Svarte 15/05/2009 kl. 14:09
kilden bruker

stemmer
2

Prøv CLPP bibliotek. Den er enkel og fleksibel bibliotek for kommandolinje parametere analysering. Header-bare og kryss-plattform. Bruker ISO C ++ og Boost C ++ bare biblioteker. IMHO er det enklere enn Boost.Program_options.

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

26 oktober 2010 - ny utgave 2.0rc. Mange feil som er løst, full reproduksjon av kildekoden, har dokumentasjon, eksempler og kommentarer blitt korrigert.

Svarte 03/05/2010 kl. 10:50
kilden bruker

stemmer
2

Ganske sent svar, men jeg har brukt GetPot for noen prosjekter: http://getpot.sourceforge.net/

Hovedtrekket: alt er i en enkelt header fil, ingen bygge problemer. Bare lagre den et sted på maskinen din og "#include" den i filen beholdningmain()

Har ikke oppdatert nylig, men pent documentated, og fungerer godt. Du kan gi det et forsøk.

Svarte 20/04/2011 kl. 19:31
kilden bruker

stemmer
6
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);
    }

}
Svarte 04/08/2011 kl. 23:24
kilden bruker

stemmer
5

AnyOption er et C ++ klasse for enkel analyse av komplekse kommandolinjealternativene. Den analyserer også alternativer fra en rsourcefile i opsjonsverdi paret format.

AnyOption implementerer de tradisjonelle POSIX stil tegnalternativer (-n) samt nyere GNU stil lange flagg (--name). Eller du kan bruke en enklere lang alternativ versjon (name) ved å spørre å ignorere alternativene POSIX stil.

Svarte 17/08/2011 kl. 15:23
kilden bruker

stemmer
51

Jeg kan foreslå malbaserte C ++ Command Line Parser Library (noen gafler på GitHub er tilgjengelig), er API veldig grei og (sitert fra nettstedet):

Biblioteket er implementert helt i header-filer som gjør det enkelt å bruke og distribuere med annen programvare. Det er lisensiert under MIT Lisens for bekymring fri distribusjon.

Dette er et eksempel fra den manuelle, farget her for enkelhet:

#include <string>
#include <iostream>
#include <algorithm>
#include <tclap/CmdLine.h>

int main(int argc, char** argv)
{

    // Wrap everything in a try block.  Do this every time,
    // because exceptions will be thrown for problems.
    try {

    // Define the command line object, and insert a message
    // that describes the program. The "Command description message"
    // is printed last in the help text. The second argument is the
    // delimiter (usually space) and the last one is the version number.
    // The CmdLine object parses the argv array based on the Arg objects
    // that it contains.
    TCLAP::CmdLine cmd("Command description message", ' ', "0.9");

    // Define a value argument and add it to the command line.
    // A value arg defines a flag and a type of value that it expects,
    // such as "-n Bishop".
    TCLAP::ValueArg<std::string> nameArg("n","name","Name to print",true,"homer","string");

    // Add the argument nameArg to the CmdLine object. The CmdLine object
    // uses this Arg to parse the command line.
    cmd.add( nameArg );

    // Define a switch and add it to the command line.
    // A switch arg is a boolean argument and only defines a flag that
    // indicates true or false.  In this example the SwitchArg adds itself
    // to the CmdLine object as part of the constructor.  This eliminates
    // the need to call the cmd.add() method.  All args have support in
    // their constructors to add themselves directly to the CmdLine object.
    // It doesn't matter which idiom you choose, they accomplish the same thing.
    TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false);

    // Parse the argv array.
    cmd.parse( argc, argv );

    // Get the value parsed by each arg.
    std::string name = nameArg.getValue();
    bool reverseName = reverseSwitch.getValue();

    // Do what you intend.
    if ( reverseName )
    {
            std::reverse(name.begin(),name.end());
            std::cout << "My name (spelled backwards) is: " << name << std::endl;
    }
    else
            std::cout << "My name is: " << name << std::endl;


    } catch (TCLAP::ArgException &e)  // catch any exceptions
    { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; }
}
Svarte 10/10/2011 kl. 11:54
kilden bruker

stemmer
21

Nok et alternativ er Lean Mean C ++ Alternativ parser:

http://optionparser.sourceforge.net

Det er en header-bare bibliotek (bare en enkelt header fil, faktisk) og i motsetning til alle de andre forslagene er det også frittstående, dvs. det har ingen avhengigheter overhodet. Spesielt er det ingen avhengighet av STL. Det trenger ikke engang bruke unntak eller noe annet som krever bibliotek støtte. Dette betyr at det kan ha sammenheng med vanlig C eller andre språk uten å innføre "fremmede" biblioteker.

Som boost :: program_options sin API tilbyr enkel direkte tilgang til alternativer, dvs. at du kan skrive kode som dette

if (opsjoner [HJELP]) ...;

og

int ordmengde = alternativer [VERBOSE] .count ();

I motsetning til boost :: program_options men dette er ganske enkelt ved hjelp av en matrise indeksert med en (brukertilført) enum. Dette tilbyr bekvemmeligheten av en assosiativ container uten vekt.

Det er godt dokumentert og har et selskap vennlige lisens (MIT).

TLMC ++ OP inneholder en fin formaterings for bruk meldinger som kan gjøre line-wrapping og kolonne justering som er nyttig hvis du lokalisere programmet, fordi det sikrer at produksjonen vil se bra ut selv på språk som har lengre meldinger. Det sparer du også plagen manuelt formatering bruk for 80 kolonner.

Svarte 24/01/2012 kl. 18:12
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more