Преобразовать vector <string> в char ** C++

У меня есть переменная vector. Мне нужно передать 9X_c++ его в метод, который принимает char** в качестве 9X_cpp входного параметра.

как это сделать? Если 9X_c возможно, мне нужно передать доступный для 9X_c записи.

Обновление 1: В инструменте для создания служебного 9X_c метода я задаю параметры как std :: vector, но 9X_c++ он автоматически устанавливает квалификатор 9X_c как &, что означает, что мое определение 9X_c метода, созданное этим инструментом, будет 9X_c выглядеть так:

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

Этот метод вызывается автоматически 9X_c++ со значениями в переданном патаметре. Теперь 9X_cxx изнутри этого метода я собираюсь вызвать 9X_cpp метод в dll в папке lib, который выглядит 9X_c так:

int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue); 

для par1 -> я передаю (char *) par1.c_str()

Мне 9X_c++ нужно знать, как передавать переменные для 9X_cxx par2 и par3 и для pRetValue. значения для 9X_c++ par2 и par3 доступны в векторе, но последний 9X_cpp параметр pRetValue - это выходной параметр, который 9X_c++ мне нужно вернуть как std :: string.

извините, если 9X_cxx я очень сбиваю с толку или задаю очень простые 9X_cpp вопросы.

42
2

  • тогда ваша операция должна быть на `* Writable`, предполагая, что **writable принимает ваш ...
3
Общее количество ответов: 3

Ответ #1

Ответ на вопрос: Преобразовать vector <string> в char ** C++

Можно решить проблему без копирования всего 9X_c std::strings, если функция не изменяет переданный в char**. В противном 9X_cxx случае я не вижу альтернативы, кроме как 9X_c скопировать все в новую структуру 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 strings {"one", "two", "three"}; std::vector cstrings; cstrings.reserve(strings.size()); for(size_t i = 0; i < strings.size(); ++i) cstrings.push_back(const_cast(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: если 9X_c функция должна изменить переданные данные:

void old_func(char** carray, size_t size) { for(size_t i = 0; i < size; ++i) std::cout << carray[i] << '\n'; } int main() { { // pre C++11 std::vector strings {"one", "two", "three"}; // guarantee contiguous, null terminated strings std::vector> vstrings; // pointers to rhose strings std::vector cstrings; vstrings.reserve(strings.size()); cstrings.reserve(strings.size()); for(size_t i = 0; i < strings.size(); ++i) { vstrings.emplace_back(strings[i].begin(), strings[i].end()); vstrings.back().push_back('\0'); cstrings.push_back(vstrings.back().data()); } old_func(cstrings.data(), cstrings.size()); } { // post C++11 std::vector strings {"one", "two", "three"}; std::vector cstrings; cstrings.reserve(strings.size()); for(auto& s: strings) cstrings.push_back(&s[0]); old_func(cstrings.data(), cstrings.size()); } } 

ПРИМЕЧАНИЕ. Изменен, чтобы 9X_c++ обеспечить лучший код.

41
1

  • @lefenzy Я отредактировал комментарий, так как он был не совсем точным. Но до `C++ 11` нет гарантии, что указатель, возвращаемый` c_str() `, указывает на фактические данные строки ...

Ответ #2

Ответ на вопрос: Преобразовать vector <string> в char ** C++

В ответе Галика есть ряд вопросов, связанных 9X_cpp с безопасностью. Вот как я бы сделал это 9X_cxx в современном C++:

#include #include #include 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 strings{"one", "two", "three"}; std::vector 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 strings{"four", "five", "six"}; std::vector cstrings{}; for(const auto& string : strings) cstrings.push_back(string.c_str()); other_old_func(cstrings.data(), cstrings.size()); std::cout << std::endl; } } 

Никакого беспорядочного 9X_c++ управления памятью или неприятных const_cast s.

Live on Coliru.

Выводы:

modifiable version one two three non-modifiable version four five six 

24
1

  • Просто имейте в виду, если вы используете `& string.front`, что в документации указано:« Эта функция не ...

Ответ #3

Ответ на вопрос: Преобразовать vector <string> в char ** C++

Самые популярные ответы на этот вопрос ожидают, что 9X_c вы передадите размер с параметрами char 9X_c++ **. Но в method_to_be_called() нет способа 9X_c передать размер для par2 и par3, поэтому 9X_cxx эти списки строк в стиле c, вероятно, будут 9X_c иметь нулевое завершение. Другими словами, последняя 9X_c строка (char *) в списке строк (char **) должна 9X_cxx быть нулевым указателем. Это распространенная 9X_c++ парадигма во многих библиотеках Си.

int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue); 

Наиболее 9X_cpp целесообразным способом обойти это, вероятно, является 9X_cpp ответ в стиле С.

//directly create char** par2 std::vector par2Vect{"one", "two", "three"}; char ** par2 = (char**) malloc( sizeof(char*)*(par2Vect.size() + 1) ); for(size_t i = 0; i < par2Vect.size(); ++i) { par2[i] = strdup(par2Vect[i].c_str()); } // set the last entry to null to signify the end of the list par2[par2Vect.size()] = nullptr; // call your library method_to_be_called(..., par2,...); // delete par2 for(size_t i = 0; i < par2Vect.size(); ++i) { // free memory for each c-style string free(par2[i]); } // free memory for outer char* array free(par2); 

1
1

  • память, выделенная с помощью `strdup`, использует` malloc` и поэтому должна быть освобождена ...