Преобразовать вектор <string> в char ** С++
У меня есть переменная vector<std::string>
. Мне нужно передать его методу, который принимает char**
как входной параметр.
как это сделать? Если возможно, мне нужно передать доступную для записи.
Обновление 1:
В инструменте создания метода службы я предоставляю параметры как std::vector, но он автоматически устанавливает квалификатор как &, что означает, что определение моего метода, сгенерированное инструментом, будет выглядеть так:
std::string SvcImpl::myMethodname ( const std::string par1, const std::vector< std::string >& par2, const std::vector< std::string >& par3 )
{
}
Этот метод вызывается автоматически со значениями в пройденном патметре.
Теперь изнутри этого метода я собираюсь вызвать метод в dll в папке lib, который выглядит так:
int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue);
для par1 → Пропускаю (char *) par1.c_str()
Мне нужно знать, как передавать переменные для par2 и par3 и для pRetValue.
значения для par2 и par3 доступны в векторе, но последний параметр pRetValue - это выходной параметр, который мне нужно вернуть как std::string.
Извините, если я очень запутан или задаю очень простые вопросы.
Ответы
Ответ 1
Можно решить проблему без копирования всех std::strings
, пока функция не изменяет переданную в char**
. В противном случае я не вижу альтернативы, кроме как скопировать все в новую структуру 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: Устанавливается на более простое решение для кода post С++ 98 (thnx to BeyelerStudios) добавлено решение, которое позволяет функции изменять переданные данные.
Ответ 2
Ответ Galik имеет ряд проблем безопасности. Вот как я сделал бы это в Modern С++:
#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
s.
Live on Coliru.
Выходы:
modifiable version
one
two
three
non-modifiable version
four
five
six