2014-09-25 59 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