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

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


Ho un vector<std::string> variabile. Devo passarlo a un metodo che accetti char** come parametro di input.


come fare questo ? Se possibile devo passarne uno scrivibile.


Aggiornamento 1:
In uno strumento per la creazione di un metodo di servizio, fornisco parametri come std::vector, ma imposta automaticamente il qualificatore come &, il che significa che la definizione del mio metodo generata dallo strumento sarà:


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

Questo metodo viene chiamato automaticamente con i valori nel patameter passato.
Ora dall'interno di questo metodo chiamerò un metodo in una dll in una cartella lib che assomiglia a:


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

per par1 --> Sto passando (char*)par1.c_str()


Ho bisogno di sapere come passare le variabili per par2 e par3 e per pRetValue.
i valori per par2 e par3 sono disponibili in vector ma l'ultimo parametro pRetValue è un parametro di output che devo restituirlo come std::string.


scusa se sono molto confuso o faccio domande molto semplici.


Risposte:


È possibile risolvere il problema senza copiare tutto il std::strings purché la funzione non modifichi il passato in char** . Altrimenti non vedo altra alternativa che copiare tutto in una nuova struttura char**` (vedi secondo esempio) .


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

ESEMPIO 2: Se la funzione deve modificare i dati passati:


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

NOTA: Rivisto per fornire un codice migliore.


Alcune risposte al codice


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.