代码之家  ›  专栏  ›  技术社区  ›  Netzdoktor

使用Boost程序选项解析任意字符串

  •  8
  • Netzdoktor  · 技术社区  · 11 年前

    我想在我的程序中实现一个类似命令行的接口。因此,我收到了遵循正常命令行语法的字符串(例如“-g foo-dp bar--help”)。由于我不想再次实现解析器,所以我想使用Boost。

    问题是:如何将字符串传递给Boost程序选项,而不是argCount和argValues的组合。我需要先将文本转换为数字(argCount)和char*数组(argValues)吗?如果是。。。有简单的方法吗?

    提前谢谢。

    2 回复  |  直到 11 年前
        1
  •  9
  •   Community Navdeep Singh    7 年前

    一种方法是标记化 std::string 变成 std::vector<std::string> ,然后将结果传递给Boost.ProgramOption command_line_parser .Boost.ProgramOption的 documentation 简要介绍了这种方法。此外,我在 this 答复

    以下是一个最小的完整示例:

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <string>
    #include <vector>
    
    #include <boost/bind.hpp>
    #include <boost/program_options.hpp>
    #include <boost/tokenizer.hpp>
    
    // copy_if was left out of the C++03 standard, so mimic the C++11
    // behavior to support all predicate types.  The alternative is to
    // use remove_copy_if, but it only works for adaptable functors.
    template <typename InputIterator,
              typename OutputIterator, 
              typename Predicate>
    OutputIterator 
    copy_if(InputIterator first,
            InputIterator last,
            OutputIterator result,
            Predicate pred)
    {
      while(first != last)
      {
        if(pred(*first))
          *result++ = *first;
        ++first;
      }
      return result;
    }
    
    /// @brief Tokenize a string.  The tokens will be separated by each non-quoted
    ///        space or equal character.  Empty tokens are removed.
    ///
    /// @param input The string to tokenize.
    ///
    /// @return Vector of tokens.
    std::vector<std::string> tokenize(const std::string& input)
    {
      typedef boost::escaped_list_separator<char> separator_type;
      separator_type separator("\\",    // The escape characters.
                               "= ",    // The separator characters.
                               "\"\'"); // The quote characters.
    
      // Tokenize the intput.
      boost::tokenizer<separator_type> tokens(input, separator);
    
      // Copy non-empty tokens from the tokenizer into the result.
      std::vector<std::string> result;
      copy_if(tokens.begin(), tokens.end(), std::back_inserter(result), 
              !boost::bind(&std::string::empty, _1));
      return result;
    }
    
    int main()
    {
      // Variables that will store parsed values.
      std::string address;
      unsigned int port;      
    
      // Setup options.
      namespace po = boost::program_options;
      po::options_description desc("Options");
      desc.add_options()
        ("address", po::value<std::string>(&address))
        ("port",    po::value<unsigned int>(&port))
        ;
    
      // Mock up input.
      std::string input = "--address 127.0.0.1 --port 12345";
    
      // Parse mocked up input.
      po::variables_map vm;
      po::store(po::command_line_parser(tokenize(input))
                    .options(desc).run(), vm);
      po::notify(vm);
    
      // Output.
      std::cout << "address = " << address << "\n"
                   "port = " << port << std::endl;
    }
    

    它产生以下输出:

    address = 127.0.0.1
    port = 12345
    
        2
  •  0
  •   aggieNick02    3 年前

    boost::program_options 具有名为的函数 split_unix 正如@FaceBro所指出的那样。它也适用于windows,因此以下是跨平台的,借用了公认答案的主要示例结构:

    int main()
    {
      // Variables that will store parsed values.
      std::string address;
      unsigned int port;      
    
      // Setup options.
      namespace po = boost::program_options;
      po::options_description desc("Options");
      desc.add_options()
        ("address", po::value<std::string>(&address))
        ("port",    po::value<unsigned int>(&port))
        ;
    
      // Mock up input.
      std::string input = "--address 127.0.0.1 --port 12345";
    
      // Parse mocked up input.
      po::variables_map vm;
      po::store(po::command_line_parser(po::split_unix(input))
                    .options(desc).run(), vm);
      po::notify(vm);
    
      // Output.
      std::cout << "address = " << address << "\n"
                   "port = " << port << std::endl;
    }