Konvertiere vector<string> in char** C++

Konvertiere vector<string> in char** C++


Ich habe einen vector<std::string> Variable. Ich muss es an eine Methode übergeben, die char** akzeptiert als Eingabeparameter.


Wie macht man das ? Wenn möglich, muss ich eine beschreibbare übergeben.


Aktualisierung 1:
In einem Tool zum Erstellen einer Dienstmethode gebe ich Parameter als std::vector an, aber es setzt automatisch den Qualifizierer als &, was bedeutet, dass meine vom Tool generierte Methodendefinition wie folgt aussieht:


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

Diese Methode wird automatisch aufgerufen, wenn Werte im Patameter übergeben werden.
Jetzt werde ich aus dieser Methode heraus eine Methode in einer DLL in einem Lib-Ordner aufrufen, die wie folgt aussieht:


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

für par1 --> Ich übergebe (char*)par1.c_str()


Ich muss wissen, wie man Variablen für par2 und par3 und für pRetValue übergibt.
Werte für par2 und par3 sind im Vektor verfügbar, aber der letzte Parameter pRetValue ist ein Ausgabeparameter, den ich als std::string zurückgeben muss.


Entschuldigung, wenn ich sehr verwirrend bin oder sehr grundlegende Fragen stelle.


Antworten:


Es ist möglich, das Problem zu lösen, ohne den gesamten std::strings herauszukopieren solange sich die Funktion nicht ändert die übergebene char** . Ansonsten sehe ich keine Alternative, als alles in eine neue char**`-Struktur (siehe zweites Beispiel) zu kopieren .


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());
}

BEISPIEL 2: Wenn die Funktion die übergebenen Daten ändern muss:


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<std::string> strings {"one", "two", "three"};
// guarantee contiguous, null terminated strings
std::vector<std::vector<char>> vstrings;
// pointers to rhose strings
std::vector<char*> 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<std::string> strings {"one", "two", "three"};
std::vector<char*> cstrings;
cstrings.reserve(strings.size());
for(auto& s: strings)
cstrings.push_back(&s[0]);
old_func(cstrings.data(), cstrings.size());
}
}

HINWEIS: Überarbeitet, um besseren Code bereitzustellen.


Einige Code-Antworten


std::string SvcImpl::myMethodname ( const std::string par1, const std::vector<
std::string >&
par2, const std::vector<
std::string >&
par3 ) { }
int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue);
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());
}
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<std::string>
strings {"one", "two", "three"};
// guarantee contiguous, null terminated strings
std::vector<std::vector<char>>
vstrings;
// pointers to rhose strings
std::vector<char*>
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<std::string>
strings {"one", "two", "three"};
std::vector<char*>
cstrings;cstrings.reserve(strings.size());
for(auto&
s: strings) cstrings.push_back(&s[0]);
old_func(cstrings.data(), cstrings.size());
} }
#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;
} }
modifiable version one two three   non-modifiable version four five six 
int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue);
//directly create char** par2 std::vector<std::string>
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);
std::vector<std::string>
vector = {"a", "std::vector", "of", "std::string"};
// Result char**. char** result = new char*[vector.size()];
for (int index = 0;
index <
vector.size();
index++) {
result[index] = const_cast<char*>(vector[index].c_str());
} // Use the result. delete[] result;
// Deallocate the memory from heap after usage.