I am implementing project specific "getopt" in C++. For this I implemented a class th开发者_StackOverflowat looks like this:
class MyGetOptions {
private:
typedef std::map<std::string, bool> optionsTbl;
optionsTbl m_optionsTbl;
int m_currentArg;
// Prohibit copy and assignment.
MyGetOptions ( const MyGetOptions &);
void operator= (const MyGetOptions &);
public:
MyGetOptions ();
inline bool addOption(std::string option, bool isArgReq);
int getOpt(int argc, char *argv[], std::string& option, std::string& optArg);
// Debug functions.
void printOptionTbl();
};
Now usage of above class by providers looks as below
MyGetOptions myOpts;
myOpts.addOption("myName", true);
myOpts.addOption("mySettings", false);
std::string optArg;
std::string option;
while( (myOpts.getOpt(argc, argv, option, optArg)) != -1 )
{
if(option.compare("myName") == 0)
{
std::cout << "The myName option is set and value is " << optArg << std::endl;
continue;
}
// ... additional options.
else if(option.compare("?") == 0 )
{
// print help and exit.
}
else
{
// print help and exist.
}
}
In the present design I am returning "?" mark if getOpt
finds an option character in argv
that was not registered, or if it detects a missing option argument. If all command line options have been parsed, then getOpt
returns -1.
I want to distinguish when ?
is returned whether argv
provided was not registered or missing option argument is provided, and also want to print the option name in while loop and show to user. What is best way to achieve this? Can any one please provide guidelines or inputs?
Instead of using global variables, I prefer to use return values with combination with "?" like as below
else if ((option.compare("?") == 0) && (getOptStatus == 0))
{
// if ? and return value 0 means finds a string in argv that is not
// registered with add options.
continue;
}
else if ((option.compare("?") == 0) && (getOptStatus == 1))
{
// if ? and return value 1 means finds an option string
// with missing option argument.
// print help and exit.
}
The standard design for getopt()
has it return the option letter that it found, or ?
on error. You would capture the option letter by assignment in the loop condition:
int opt;
while ((opt = myOpts.getOpt(argc, argv, option, optArg)) != -1)
{
...analyze the option returned...
}
The standard getopt()
has a global variable optarg
to point to the argument; the reference parameter in C++ is a better choice (we might quibble about std::string
versus char *
).
As to error detection, the standard getopt()
has variables optopt
and opterr
to assist. The optopt
contains the letter of the option that triggered the error. The opterr
can be set to 0 to indicate that getopt()
should not report errors; by default, it writes an error to cerr
for you.
In C++, you would avoid using global variables, but you could use some extra (private) member variables to record such details, and provide accessor functions to let you find out what is going on.
Program options have been done before. Do not reinvent unless you really must. Please consider Boost.Program_options.
精彩评论