2014-09-25 6 views
12

में कनवर्ट करें मेरे पास vector<std::string> चर है। मुझे इसे एक विधि पर पास करने की आवश्यकता है जो इनपुट पैरामीटर के रूप में char** स्वीकार करता है।वेक्टर <string> को चार ** सी ++

यह कैसे करें? यदि संभव हो तो मुझे एक लिखने योग्य व्यक्ति को पास करने की आवश्यकता है।

अद्यतन 1: एक सेवा विधि बनाने के लिए एक उपकरण में, मैं std :: वेक्टर के रूप में मानकों को देते हैं, लेकिन यह अपने आप मेरी विधि उपकरण द्वारा उत्पन्न परिभाषा के रूप में दिखाई देगा जिसका अर्थ है & के रूप में क्वालीफायर, सेट:

std::string SvcImpl::myMethodname (const std::string par1, const std::vector<  std::string >& par2, const std::vector<std::string>& par3) 
{ 

} 

इस विधि को स्वचालित रूप से पास किए गए पेटामीटर में मूल्यों के साथ बुलाया जाता है। अब से इस विधि के अंदर मैं जो की तरह दिखता है एक lib फ़ोल्डर में एक dll में एक विधि कॉल करने के लिए जा रहा हूँ:

int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue); 
par1 के लिए

-> मैं गुजर रहा हूँ (चार *) par1.c_str()

मुझे पता होना चाहिए कि par2 और par3 और pRetValue के लिए चर कैसे पास करें। वेक्टर में par2 और par3 के लिए मान उपलब्ध हैं लेकिन अंतिम पैरामीटर pRetValue एक आउटपुट पैरामीटर है जिसे मुझे std :: string के रूप में वापस करने की आवश्यकता है।

क्षमा करें अगर मैं बहुत भ्रमित हूं या बहुत बुनियादी प्रश्न पूछ रहा हूं।

+1

तो अपने ऑपरेशन, 'writable' पर * होना चाहिए संभालने ** लिखने योग्य अपने चार ** परम स्वीकार कर रहा है। –

+1

मुझे लगता है कि आपको अपने सभी स्ट्रिंग डेटा के पते को स्टोर करने के लिए एक नया 'std :: vector 'बनाने की आवश्यकता होगी। – Galik

+0

इस विधि को आप वास्तव में क्या कर रहे हैं? – Wlerin

उत्तर

18

यह रूप में लंबे समय सभी std::strings बाहर को कॉपी समारोह रूपchar** में पारित संशोधित नहीं करता है बिना समस्या का समाधान संभव है। अन्यथा मैं कोई नया विकल्प नहीं देख सकता लेकिन सब कुछ एक नए चार ** 'संरचना में देखें (दूसरा उदाहरण देखें)

void old_func(char** carray, size_t size) 
{ 
    for(size_t i = 0; i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    std::vector<std::string> strings {"one", "two", "three"}; 
    std::vector<char*> cstrings; 
    cstrings.reserve(strings.size()); 

    for(size_t i = 0; i < strings.size(); ++i) 
     cstrings.push_back(const_cast<char*>(strings[i].c_str())); 

    // Do not change any of the strings here as that will 
    // invalidate the new data structure that relies on 
    // the returned values from `c_str()` 
    // 
    // This is not an issue after C++11 as long as you don't 
    // increase the length of a string (as that may cause reallocation) 

    if(!cstrings.empty()) 
     old_func(&cstrings[0], cstrings.size()); 
} 

उदाहरण 2: समारोह को संशोधित करना आवश्यक है डेटा में पारित:

void old_func(char** carray, size_t size) 
{ 
    for(size_t i = 0; i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    std::vector<std::string> strings { "one", "two", "three"}; 
    char** cstrings = new char*[strings.size()]; 

    for(size_t i = 0; i < strings.size(); ++i) 
    { 
     cstrings[i] = new char[strings[i].size() + 1]; 
     std::strcpy(cstrings[i], strings[i].c_str()); 
    } 

    // Now the function can do what it likes (within the bounds) 
    // with the passed in structure 

    old_func(cstrings, strings.size()); 

    // clean up memory 

    for(size_t i = 0; i < strings.size(); ++i) 
     delete[] cstrings[i]; 

    delete[] cstrings; 
} 

EDIT5: पद सी ++ 98 कोड (के लिए एक सरल समाधान पर बसे करने के लिए thnx BeyelerStudios) ने एक समाधान जोड़ा जो फ़ंक्शन को डेटा में पारित करने की अनुमति देता है।

+0

अच्छा, हालांकि दूसरे संस्करण में मैं पॉइंटर सरणी को पकड़ने के लिए एक वेक्टर या कम से कम एक अद्वितीय_प्टर का उपयोग करता हूं, और पॉइंटर्स को हटाने के लिए किसी प्रकार की स्कोप_एक्सिट सुविधा का उपयोग करता हूं। यदि कोई भी व्यक्तिगत स्ट्रिंग आवंटन यहां विफल रहता है, तो पिछले सभी के साथ पॉइंटर सरणी लीक हो जाती है। –

+0

आपके कोड की टिप्पणी में, आपने लिखा है कि "यह C++ 11 के बाद कोई समस्या नहीं है।" क्या आप कृपया बता सकते हैं क्यों? – bernie

+1

@lefenzy मैंने टिप्पणी संपादित की क्योंकि यह पूरी तरह से सटीक नहीं था। लेकिन 'सी ++ 11' से पहले इस बात की कोई गारंटी नहीं है कि पॉइंटर 'c_str() 'अंक द्वारा स्ट्रिंग के वास्तविक डेटा पर लौटाया गया है (यह एक अस्थायी बफर हो सकता है)। 'सी ++ 11' के बाद यह स्ट्रिंग्स वास्तविक डेटा को इंगित करने की गारंटी है। यह केवल तभी अमान्य है जब आप स्ट्रिंग की लंबाई * बढ़ाएं। – Galik

7

गैलिक के उत्तर में कई सुरक्षा समस्याएं हैं। यहाँ कैसे मैं आधुनिक सी ++ में ऐसा होता है:

#include <iostream> 
#include <string> 
#include <vector> 

void old_func(char** carray, std::size_t size) 
{ 
    for(std::size_t i(0); i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

void other_old_func(const char** carray, std::size_t size) 
{ 
    for(std::size_t i(0); i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    { 
     std::cout << "modifiable version\n"; 
     std::vector<std::string> strings{"one", "two", "three"}; 
     std::vector<char*> cstrings{}; 

     for(auto& string : strings) 
      cstrings.push_back(&string.front()); 

     old_func(cstrings.data(), cstrings.size()); 

     std::cout << "\n\n"; 
    } 
    { 
     std::cout << "non-modifiable version\n"; 
     std::vector<std::string> strings{"four", "five", "six"}; 
     std::vector<const char*> cstrings{}; 

     for(const auto& string : strings) 
      cstrings.push_back(string.c_str()); 

     other_old_func(cstrings.data(), cstrings.size()); 
     std::cout << std::endl; 
    } 
} 

कोई गंदा स्मृति प्रबंधन या बुरा const_cast रों।

Live on Coliru.

आउटपुट:

modifiable version 
one 
two 
three 


non-modifiable version 
four 
five 
six 
संबंधित मुद्दे