best way to copy a vector<string> to char**

M

Matt Garman

What is the "best" way to copy a vector of strings to an array of
character strings? By "best", I mean most elegantly/tersely written,
but without any sacrifice in performance.

I'm writing an application using C++ and the STL for handling my data.
Unfortunately, I must interact with a (vanilla) C API. I use vectors of
strings (for simplicity and less memory hassle), but the function calls
for this API require arrays of character strings (char**).

Below is some code to copy a vector of strings to an array of character
strings. It works (based on minimal testing anyway :). I'm just
curious if there is a "better" way to do it.

Thanks,
Matt
email at: http://raw-sewage.net/index.php?file=email


// this code is public domain
// compiles with the GNU C++ compiler (g++) v3.2.3

#include <string>
#include <vector>
#include <iostream>
#include <cstring>

using namespace std;

int main(int argc, char** argv)
{
// handy typedefs just to save some typing
typedef std::vector<std::string> strvec_t;
typedef std::vector<std::string>::iterator strveciter_t;

strvec_t strvec;

// fill the string vector with some sample strings
strvec.push_back("Hello"); strvec.push_back(", ");
strvec.push_back("world"); strvec.push_back("... ");
strvec.push_back("How "); strvec.push_back("are ");
strvec.push_back("you "); strvec.push_back("today");
strvec.push_back("?");

// print out the strings (just for sanity)
for (strveciter_t ii=strvec.begin(); ii!=strvec.end(); ++ii)
cout << *ii;
cout << endl;

// allocate memory for an array of character strings
char** cstr = new char*[strvec.size()];

// for each string, allocate memory in the character array and copy
for (unsigned long i=0; i<strvec.size(); i++) {
cstr = new char[strvec.size()+1];
strncpy(cstr, strvec.c_str(), strvec.size());
}

// print out the newly copied strings
for (unsigned long i=0; i<strvec.size(); i++) cout << cstr;
cout << endl;

// free dynamic memory
for (unsigned long i=0; i<strvec.size(); i++) delete[] cstr;
delete[] cstr;

return 0;
}
 
G

Gianni Mariani

Matt said:
What is the "best" way to copy a vector of strings to an array of
character strings? By "best", I mean most elegantly/tersely written,
but without any sacrifice in performance.

I'm writing an application using C++ and the STL for handling my data.
Unfortunately, I must interact with a (vanilla) C API. I use vectors of
strings (for simplicity and less memory hassle), but the function calls
for this API require arrays of character strings (char**).

Below is some code to copy a vector of strings to an array of character
strings. It works (based on minimal testing anyway :). I'm just
curious if there is a "better" way to do it.

Here is another version with a helper class that does what you did but
in a little less.

This version does not allocate anything with new - instead it just uses
the c_str() value as the "char *" which I took the liberty to change to
const char *. Anyhow - if that does not work for you, there is nothing
stopping you from "new"ing whatever you want and deleting it in the
constuctor.

This is a (poor) demonstration of the "low threshold to create a new
class" rule.


// this code is public domain
// compiles with the GNU C++ compiler (g++) v3.2.3

#include <string>
#include <vector>
#include <iostream>
#include <cstring>

using namespace std;

class VectCharPP
{
public:

vector<const char*> ptrs;

VectCharPP( const vector< string > & v )
: ptrs( v.size() + 1 )
{
long i= v.size();

ptrs[ i ] = 0;

for ( --i ; i >= 0; --i ) {
ptrs[ i ] = v[ i ].c_str();
}
}

operator const char ** ()
{
return & ( ptrs[ 0 ] );
}

};


int main(int argc, char** argv)
{
// handy typedefs just to save some typing
typedef std::vector<std::string> strvec_t;
typedef std::vector<std::string>::iterator strveciter_t;

strvec_t strvec;

// fill the string vector with some sample strings
strvec.push_back("Hello"); strvec.push_back(", ");
strvec.push_back("world"); strvec.push_back("... ");
strvec.push_back("How "); strvec.push_back("are ");
strvec.push_back("you "); strvec.push_back("today");
strvec.push_back("?");

// print out the strings (just for sanity)
for (strveciter_t ii=strvec.begin(); ii!=strvec.end(); ++ii)
cout << *ii;
cout << endl;

// allocate new vector here.
VectCharPP cstr_v = strvec;

const char** cstr = cstr_v;

// NOTE THAT cstr only lives as long as the VectCharPP object ...
// since this is a legacy interface we assume this policy is easy
// easy to adhere to.

// print out the newly copied strings
for (unsigned long i=0; cstr; i++) cout << cstr;
cout << endl;

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,526
Members
44,997
Latest member
mileyka

Latest Threads

Top