本文由 @lonelyrains 出品,转载请注明出处。
文章链接: http://blog.csdn.net/lonelyrains/article/details/46426645
/*! " The CommandLineParser class is designed for command line arguments parsing " "Keys map: " "Before you start to work with CommandLineParser you have to create a map for keys. " " It will look like this " " const char* keys = " " { " " { s| string| 123asd |string parameter} " " { d| digit | 100 |digit parameter } " " { c|noCamera|false |without camera } " " { 1| |some text|help } " " { 2| |333 |another help } " " }; " "Usage syntax: " " "{" - start of parameter string. " " "}" - end of parameter string " " "|" - separator between short name, full name, default value and help " "Supported syntax: " " --key1=arg1 <If a key with '--' must has an argument " " you have to assign it through '=' sign.> " "<If the key with '--' doesn't have any argument, it means that it is a bool key> " " -key2=arg2 <If a key with '-' must has an argument " " you have to assign it through '=' sign.> " "If the key with '-' doesn't have any argument, it means that it is a bool key " " key3 <This key can't has any parameter> " "Usage: " " Imagine that the input parameters are next: " " -s=string_value --digit=250 --noCamera lena.jpg 10000 " " CommandLineParser parser(argc, argv, keys) - create a parser object " " parser.get<string>("s" or "string") will return you first parameter value " " parser.get<string>("s", false or "string", false) will return you first parameter value " " without spaces in end and begin " " parser.get<int>("d" or "digit") will return you second parameter value. " " It also works with 'unsigned int', 'double', and 'float' types> " " parser.get<bool>("c" or "noCamera") will return you true . " " If you enter this key in commandline> " " It return you false otherwise. " " parser.get<string>("1") will return you the first argument without parameter (lena.jpg) " " parser.get<int>("2") will return you the second argument without parameter (10000) " " It also works with 'unsigned int', 'double', and 'float' types " */ class CV_EXPORTS CommandLineParser { public: //! the default constructor CommandLineParser(int argc, const char* const argv[], const char* key_map); //! get parameter, you can choose: delete spaces in end and begin or not template<typename _Tp> _Tp get(const std::string& name, bool space_delete=true) { if (!has(name)) { return _Tp(); } std::string str = getString(name); return analyzeValue<_Tp>(str, space_delete); } //! print short name, full name, current value and help for all params void printParams(); protected: std::map<std::string, std::vector<std::string> > data; std::string getString(const std::string& name); bool has(const std::string& keys); template<typename _Tp> _Tp analyzeValue(const std::string& str, bool space_delete=false); template<typename _Tp> static _Tp getData(const std::string& str) { _Tp res = _Tp(); std::stringstream s1(str); s1 >> res; return res; } template<typename _Tp> _Tp fromStringNumber(const std::string& str);//the default conversion function for numbers }; template<> CV_EXPORTS bool CommandLineParser::get<bool>(const std::string& name, bool space_delete); template<> CV_EXPORTS std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete); template<> CV_EXPORTS int CommandLineParser::analyzeValue<int>(const std::string& str, bool space_delete); template<> CV_EXPORTS unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool space_delete); template<> CV_EXPORTS uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool space_delete); template<> CV_EXPORTS float CommandLineParser::analyzeValue<float>(const std::string& str, bool space_delete); template<> CV_EXPORTS double CommandLineParser::analyzeValue<double>(const std::string& str, bool space_delete);
cmdparser.cpp
#include "precomp.hpp" #include <iostream> #include <iomanip> using namespace std; using namespace cv; namespace { void helpParser() { printf(" The CommandLineParser class is designed for command line arguments parsing " "Keys map: " "Before you start to work with CommandLineParser you have to create a map for keys. " " It will look like this " " const char* keys = " " { " " { s| string| 123asd |string parameter} " " { d| digit | 100 |digit parameter } " " { c|noCamera|false |without camera } " " { 1| |some text|help } " " { 2| |333 |another help } " " }; " "Usage syntax: " " "{" - start of parameter string. " " "}" - end of parameter string " " "|" - separator between short name, full name, default value and help " "Supported syntax: " " --key1=arg1 <If a key with '--' must has an argument " " you have to assign it through '=' sign.> " "<If the key with '--' doesn't have any argument, it means that it is a bool key> " " -key2=arg2 <If a key with '-' must has an argument " " you have to assign it through '=' sign.> " "If the key with '-' doesn't have any argument, it means that it is a bool key " " key3 <This key can't has any parameter> " "Usage: " " Imagine that the input parameters are next: " " -s=string_value --digit=250 --noCamera lena.jpg 10000 " " CommandLineParser parser(argc, argv, keys) - create a parser object " " parser.get<string>("s" or "string") will return you first parameter value " " parser.get<string>("s", false or "string", false) will return you first parameter value " " without spaces in end and begin " " parser.get<int>("d" or "digit") will return you second parameter value. " " It also works with 'unsigned int', 'double', and 'float' types> " " parser.get<bool>("c" or "noCamera") will return you true . " " If you enter this key in commandline> " " It return you false otherwise. " " parser.get<string>("1") will return you the first argument without parameter (lena.jpg) " " parser.get<int>("2") will return you the second argument without parameter (10000) " " It also works with 'unsigned int', 'double', and 'float' types " ); } vector<string> split_string(const string& str, const string& delimiters) { vector<string> res; string split_str = str; size_t pos_delim = split_str.find(delimiters); while ( pos_delim != string::npos) { if (pos_delim == 0) { res.push_back(""); split_str.erase(0, 1); } else { res.push_back(split_str.substr(0, pos_delim)); split_str.erase(0, pos_delim + 1); } pos_delim = split_str.find(delimiters); } res.push_back(split_str); return res; } string del_space(string name) { while ((name.find_first_of(' ') == 0) && (name.length() > 0)) name.erase(0, 1); while ((name.find_last_of(' ') == (name.length() - 1)) && (name.length() > 0)) name.erase(name.end() - 1, name.end()); return name; } }//namespace static bool keyIsNumber(const std::string & option, size_t start) { bool isNumber = true; size_t end = option.find_first_of('=', start); end = option.npos == end ?option.length() : end; for ( ; start < end; ++start) if (!isdigit(option[start])) { isNumber = false; break; } return isNumber; } CommandLineParser::CommandLineParser(int argc, const char* const argv[], const char* keys) { std::string keys_buffer; std::string values_buffer; std::string buffer; std::string curName; std::vector<string> keysVector; std::vector<string> paramVector; std::map<std::string, std::vector<std::string> >::iterator it; size_t flagPosition; int currentIndex = 1; //bool isFound = false; bool withNoKey = false; bool hasValueThroughEq = false; keys_buffer = keys; while (!keys_buffer.empty()) { flagPosition = keys_buffer.find_first_of('}'); flagPosition++; buffer = keys_buffer.substr(0, flagPosition); keys_buffer.erase(0, flagPosition); flagPosition = buffer.find('{'); if (flagPosition != buffer.npos) buffer.erase(flagPosition, (flagPosition + 1)); flagPosition = buffer.find('}'); if (flagPosition != buffer.npos) buffer.erase(flagPosition); paramVector = split_string(buffer, "|"); while (paramVector.size() < 4) paramVector.push_back(""); buffer = paramVector[0]; buffer += '|' + paramVector[1]; //if (buffer == "") CV_ERROR(CV_StsBadArg, "In CommandLineParser need set short and full name"); paramVector.erase(paramVector.begin(), paramVector.begin() + 2); data[buffer] = paramVector; } buffer.clear(); keys_buffer.clear(); paramVector.clear(); for (int i = 1; i < argc; i++) { if (!argv[i]) break; curName = argv[i]; size_t nondash = curName.find_first_not_of("-"); if (nondash == 0 || nondash == curName.npos || keyIsNumber(curName, nondash)) withNoKey = true; else curName.erase(0, nondash); if (curName.find('=') != curName.npos) { hasValueThroughEq = true; buffer = curName; curName.erase(curName.find('=')); buffer.erase(0, (buffer.find('=') + 1)); } values_buffer = del_space(values_buffer); for(it = data.begin(); it != data.end(); it++) { keys_buffer = it->first; keysVector = split_string(keys_buffer, "|"); for (size_t j = 0; j < keysVector.size(); j++) keysVector[j] = del_space(keysVector[j]); values_buffer = it->second[0]; if (((curName == keysVector[0]) || (curName == keysVector[1])) && hasValueThroughEq) { it->second[0] = buffer; //isFound = true; break; } if (!hasValueThroughEq && ((curName == keysVector[0]) || (curName == keysVector[1])) && ( values_buffer.find("false") != values_buffer.npos || values_buffer == "" )) { it->second[0] = "true"; //isFound = true; break; } if (!hasValueThroughEq && (values_buffer.find("false") == values_buffer.npos) && ((curName == keysVector[0]) || (curName == keysVector[1]))) { it->second[0] = argv[++i]; //isFound = true; break; } if (withNoKey) { std::string noKeyStr = it->first; if(atoi(noKeyStr.c_str()) == currentIndex) { it->second[0] = curName; currentIndex++; //isFound = true; break; } } } withNoKey = false; hasValueThroughEq = false; //isFound = false; } } bool CommandLineParser::has(const std::string& keys) { std::map<std::string, std::vector<std::string> >::iterator it; std::vector<string> keysVector; for(it = data.begin(); it != data.end(); it++) { keysVector = split_string(it->first, "|"); for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]); if (keysVector.size() == 1) keysVector.push_back(""); if ((del_space(keys).compare(keysVector[0]) == 0) || (del_space(keys).compare(keysVector[1]) == 0)) return true; } return false; } std::string CommandLineParser::getString(const std::string& keys) { std::map<std::string, std::vector<std::string> >::iterator it; std::vector<string> valueVector; for(it = data.begin(); it != data.end(); it++) { valueVector = split_string(it->first, "|"); for (size_t i = 0; i < valueVector.size(); i++) valueVector[i] = del_space(valueVector[i]); if (valueVector.size() == 1) valueVector.push_back(""); if ((del_space(keys).compare(valueVector[0]) == 0) || (del_space(keys).compare(valueVector[1]) == 0)) return it->second[0]; } return string(); } template<typename _Tp> _Tp CommandLineParser::fromStringNumber(const std::string& str)//the default conversion function for numbers { return getData<_Tp>(str); } void CommandLineParser::printParams() { int col_p = 30; int col_d = 50; std::map<std::string, std::vector<std::string> >::iterator it; std::vector<string> keysVector; std::string buf; for(it = data.begin(); it != data.end(); it++) { keysVector = split_string(it->first, "|"); for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]); cout << " "; buf = ""; if (keysVector[0] != "") { buf = "-" + keysVector[0]; if (keysVector[1] != "") buf += ", --" + keysVector[1]; } else if (keysVector[1] != "") buf += "--" + keysVector[1]; if (del_space(it->second[0]) != "") buf += "=[" + del_space(it->second[0]) + "]"; cout << setw(col_p-2) << left << buf; if ((int)buf.length() > col_p-2) { cout << endl << " "; cout << setw(col_p-2) << left << " "; } buf = ""; if (del_space(it->second[1]) != "") buf += del_space(it->second[1]); for(;;) { bool tr = ((int)buf.length() > col_d-2) ?
true: false; std::string::size_type pos = 0; if (tr) { pos = buf.find_first_of(' '); for(;;) { if (buf.find_first_of(' ', pos + 1 ) < (std::string::size_type)(col_d-2) && buf.find_first_of(' ', pos + 1 ) != std::string::npos) pos = buf.find_first_of(' ', pos + 1); else break; } pos++; cout << setw(col_d-2) << left << buf.substr(0, pos) << endl; } else { cout << setw(col_d-2) << left << buf<< endl; break; } buf.erase(0, pos); cout << " "; cout << setw(col_p-2) << left << " "; } } } template<> bool CommandLineParser::get<bool>(const std::string& name, bool space_delete) { std::string str_buf = getString(name); if (space_delete && str_buf != "") { str_buf = del_space(str_buf); } if (str_buf == "true") return true; return false; } template<> std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete) { if (space_delete) { return del_space(str); } return str; } template<> int CommandLineParser::analyzeValue<int>(const std::string& str, bool /*space_delete*/) { return fromStringNumber<int>(str); } template<> unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool /*space_delete*/) { return fromStringNumber<unsigned int>(str); } template<> uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool /*space_delete*/) { return fromStringNumber<uint64>(str); } template<> float CommandLineParser::analyzeValue<float>(const std::string& str, bool /*space_delete*/) { return fromStringNumber<float>(str); } template<> double CommandLineParser::analyzeValue<double>(const std::string& str, bool /*space_delete*/) { return fromStringNumber<double>(str); }
好多东西真的不用自己写. 联想非常重要.