且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

命令行解析器

更新时间:2022-09-16 20:47:42

本文由 @lonelyrains 出品,转载请注明出处。

 
文章链接: http://blog.csdn.net/lonelyrains/article/details/46426645


opencv2.4.8  core.hpp 

/*!
"\nThe CommandLineParser class is designed for command line arguments parsing\n"
           "Keys map: \n"
           "Before you start to work with CommandLineParser you have to create a map for keys.\n"
           "    It will look like this\n"
           "    const char* keys =\n"
           "    {\n"
           "        {    s|  string|  123asd |string parameter}\n"
           "        {    d|  digit |  100    |digit parameter }\n"
           "        {    c|noCamera|false    |without camera  }\n"
           "        {    1|        |some text|help            }\n"
           "        {    2|        |333      |another help    }\n"
           "    };\n"
           "Usage syntax: \n"
           "    \"{\" - start of parameter string.\n"
           "    \"}\" - end of parameter string\n"
           "    \"|\" - separator between short name, full name, default value and help\n"
           "Supported syntax: \n"
           "    --key1=arg1  <If a key with '--' must has an argument\n"
           "                  you have to assign it through '=' sign.> \n"
           "<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
           "    -key2=arg2   <If a key with '-' must has an argument \n"
           "                  you have to assign it through '=' sign.> \n"
           "If the key with '-' doesn't have any argument, it means that it is a bool key\n"
           "    key3                 <This key can't has any parameter> \n"
           "Usage: \n"
           "      Imagine that the input parameters are next:\n"
           "                -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
           "    CommandLineParser parser(argc, argv, keys) - create a parser object\n"
           "    parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
           "    parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
           "                                                                without spaces in end and begin\n"
           "    parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
           "                    It also works with 'unsigned int', 'double', and 'float' types>\n"
           "    parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
           "                                If you enter this key in commandline>\n"
           "                                It return you false otherwise.\n"
           "    parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
           "    parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
           "                          It also works with 'unsigned int', 'double', and 'float' types \n"
*/
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("\nThe CommandLineParser class is designed for command line arguments parsing\n"
           "Keys map: \n"
           "Before you start to work with CommandLineParser you have to create a map for keys.\n"
           "    It will look like this\n"
           "    const char* keys =\n"
           "    {\n"
           "        {    s|  string|  123asd |string parameter}\n"
           "        {    d|  digit |  100    |digit parameter }\n"
           "        {    c|noCamera|false    |without camera  }\n"
           "        {    1|        |some text|help            }\n"
           "        {    2|        |333      |another help    }\n"
           "    };\n"
           "Usage syntax: \n"
           "    \"{\" - start of parameter string.\n"
           "    \"}\" - end of parameter string\n"
           "    \"|\" - separator between short name, full name, default value and help\n"
           "Supported syntax: \n"
           "    --key1=arg1  <If a key with '--' must has an argument\n"
           "                  you have to assign it through '=' sign.> \n"
           "<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
           "    -key2=arg2   <If a key with '-' must has an argument \n"
           "                  you have to assign it through '=' sign.> \n"
           "If the key with '-' doesn't have any argument, it means that it is a bool key\n"
           "    key3                 <This key can't has any parameter> \n"
           "Usage: \n"
           "      Imagine that the input parameters are next:\n"
           "                -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
           "    CommandLineParser parser(argc, argv, keys) - create a parser object\n"
           "    parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
           "    parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
           "                                                                without spaces in end and begin\n"
           "    parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
           "                    It also works with 'unsigned int', 'double', and 'float' types>\n"
           "    parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
           "                                If you enter this key in commandline>\n"
           "                                It return you false otherwise.\n"
           "    parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
           "    parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
           "                          It also works with 'unsigned int', 'double', and 'float' types \n"
           );
}

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


好多东西真的不用自己写.    联想非常重要.







本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5174490.html,如需转载请自行联系原作者