2013-08-22 7 views
5

मैं अपने प्रोग्राम के अंदर इंटरफ़ेस जैसे कमांड लाइन को कार्यान्वित करना चाहता हूं। इसलिए मुझे स्ट्रिंग मिलती हैं जो सामान्य कमांड लाइन सिंटैक्स का पालन करती हैं (उदा। "-जी foo -dp bar --help")। चूंकि मैं फिर से पार्सर को लागू नहीं करना चाहता, इसलिए मैं बूस्ट का उपयोग करना चाहता हूं।एक मनमानी स्ट्रिंग को पार्स करने के लिए बूस्ट प्रोग्राम विकल्प का उपयोग करें

सवाल यह है: मैं argCount और argValues ​​के संयोजन के बजाय प्रोग्राम विकल्पों को बूस्ट करने के लिए स्ट्रिंग कैसे पास कर सकता हूं। क्या मुझे टेक्स्ट को पहले नंबर (argCount) और char * array (argValues) में बदलने की आवश्यकता है? और यदि हां ... क्या ऐसा करने का कोई आसान तरीका है?

अग्रिम धन्यवाद।

+0

कारण है कि आप एक स्ट्रिंग से होकर गुजरेगा

यहाँ एक न्यूनतम पूरा उदाहरण है? आपको अपने सी ++ प्रोग्राम में पहले से ही ** ** के रूप में विकल्प मिलते हैं? – codeling

+0

मैं एक std :: स्ट्रिंग के चारों ओर पास करने के लिए यूनिक्स सॉकेट (asio :: local) का उपयोग करता हूं। अब मैं प्रोग्राम विकल्पों का उपयोग करके इस स्ट्रिंग को पार्स करना चाहता हूं। समस्या यह है कि उदाहरण में केवल po :: parse_command_line (एसी, एवी, desc) शामिल है, लेकिन मेरे पास एवी नहीं है। मेरे पास एक पूर्ण स्ट्रिंग है जिसमें तर्क शामिल हैं। – Darneas

+0

@ कोडिंग क्योंकि मैं एक यूनिट टेस्ट लिख रहा हूं। – Eyal

उत्तर

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 
+0

हमें लिनक्स के तहत अपने स्वयं के टोकननाइज की आवश्यकता नहीं है, बूस्ट split_unix का उपयोग करें। – FaceBro

संबंधित मुद्दे