2014-09-25 60 views
12

我有一個vector<std::string>變量。我需要將它傳遞給接受char**作爲輸入參數的方法。將矢量<string>轉換爲char ** C++

該怎麼辦?如果可能,我需要通過一個可寫的。

更新1: 在創建服務方法的工具,我給參數的std ::載體,但它會自動將限定符&,這意味着該工具生成我的方法定義會看看:

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

} 

該方法會自動調用傳入的patameter中的值。 現在,從這個方法裏面我要調用DLL中的方法,它看起來像一個lib文件夾:

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',假設**寫在接受您的字符** PARAM。 – 2014-09-25 06:34:35

+1

我想你將需要生成一個新的'std :: vector '來存儲所有字符串數據的地址。 – Galik 2014-09-25 06:44:27

+0

你傳遞給它的方法是什麼? – Wlerin 2014-09-25 06:45:27

回答

18

只要函數不修改傳入的char**,就可以解決問題而不需要複製全部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:結算上的簡單的解決方案用於後C++ 98代碼(日Thnx到BeyelerStudios)增加了一個解決方案,允許函數修改傳入的數據。

+0

好,雖然在第二個版本中,我會使用一個向量或至少一個unique_ptr來存放指針數組,以及某種scope_exit設施來刪除裏面的指針。如果任何一個單獨的字符串分配在這裏失敗,所有先前的加上指針數組都會泄漏。 – 2014-09-29 12:32:37

+0

在你的代碼的評論中,你寫道:「這不是C++ 11之後的問題。」你能解釋爲什麼嗎? – bernie 2017-08-23 17:16:56

+1

@lefenzy我編輯了評論,因爲它不完全準確。但在「C++ 11」之前,不能保證'c_str()'返回的指針指向字符串的實際數據(它可能是一個臨時緩衝區)。在'C++ 11'之後,它保證指向字符串的實際數據。只有在增加字符串的長度時纔會失效。 – Galik 2017-08-23 17:41:23

7

Galik的答案有一些安全問題。這裏是我會怎麼做現代C++:

#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