Подтвердить что ты не робот

Преобразовать вектор <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.

Извините, если я очень запутан или задаю очень простые вопросы.

4b9b3361

Ответ 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