vector<string> to char*[]

  • Thread starter Andrew Wingorodov
  • Start date
A

Andrew Wingorodov

i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).

how i can make its simple?
there may be ready solutions?
 
A

Alf P. Steinbach

* Andrew Wingorodov:
i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).

how i can make its simple?
there may be ready solutions?

std::vector<string> arg;
...

std::vector<char const*> v( arg.size() );
for( size_t i = 0; i < v.size(); ++i ) { v = arg.c_str(); }
blahblah( &v[0] );

Cheers, & hth.,

- Alf
 
J

Joel Yliluoma

i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).

how i can make its simple?
there may be ready solutions?

I assume you are talking about some POSIX system (indicated by execv).
Since execv replaces the current running program with the executed
one, worries of memory leaks do not apply (except when an error happens).
So you can do this:

const char** argv = new const char*[ arg.size() ];
for(size_t a=0; a<arg.size(); ++a) argv[a] = arg[a].c_str();
execv(... argv ...);
// cleanup when error happened
delete[] argv;
 
A

Andrew Wingorodov

Joel Yliluoma said:
const char** argv = new const char*[ arg.size() ];
for(size_t a=0; a<arg.size(); ++a) argv[a] = arg[a].c_str();
execv(... argv ...);
// cleanup when error happened
delete[] argv;

i do correct?

//
const char**
args::constchar (const std::vector<std::string>& arg_)
{
static std::auto_ptr<const char*> v;
v = (std::auto_ptr<const char*>) new const char* [arg_.size()+1];

std::vector<std::string>::const_iterator i = arg_.begin();
size_t j;

for (; i != arg_.end (); ++i)
{
v.get()[j++] = (*i).c_str() ;
}

v.get()[j] = NULL;
return v.get();
}
 
A

Alf P. Steinbach

* Andrew Wingorodov:
Joel Yliluoma said:
const char** argv = new const char*[ arg.size() ];
for(size_t a=0; a<arg.size(); ++a) argv[a] = arg[a].c_str();
execv(... argv ...);
// cleanup when error happened
delete[] argv;

i do correct?

//
const char**
args::constchar (const std::vector<std::string>& arg_)
{
static std::auto_ptr<const char*> v;
v = (std::auto_ptr<const char*>) new const char* [arg_.size()+1];

auto_ptr calls delete, whereas you need delete[]. Not that it matters
much in practice for a char array. But formally UB.

std::vector<std::string>::const_iterator i = arg_.begin();
size_t j;

for (; i != arg_.end (); ++i)
{
v.get()[j++] = (*i).c_str() ;
}

v.get()[j] = NULL;
return v.get();
}

When the function returns, the auto_ptr calls delete. As mentioned
that's just formally UB, but if that delete works, the effect is that
the function returns a pointer to deallocated memory.

Try what I posted earlier, it's safe:

std::vector<string> arg;
...

std::vector<char const*> v( arg.size() );
for( size_t i = 0; i < v.size(); ++i ) { v = arg.c_str(); }
blahblah( &v[0] );

If you have any questions, just ask.

Cheers, & hth.,

- Alf
 
A

Andrew Wingorodov

Alf P. Steinbach said:
auto_ptr calls delete, whereas you need delete[]. Not that it matters
much in practice for a char array. But formally UB.

When the function returns, the auto_ptr calls delete. As mentioned

Try what I posted earlier, it's safe:

i got it, 10x
but i'm afraid that the vector isn't equiv to the array of poiter to chars

may be this is a better way?

//--code--

class constchar
{
private:
const char** v;

public:
constchar (const std::vector<std::string>& arg_);

inline virtual ~constchar () { delete [] v; }

inline operator const char** () const { return v; }

}; //!class constchar

//
constchar::constchar (const std::vector<std::string>& arg_)
{
v = new const char* [arg_.size()+1];
std::vector<std::string>::const_iterator i = arg_.begin();
size_t j;

for (j^=j; i != arg_.end (); ++i)
{
v[j++] = (*i).c_str() ;
}

v[j] = NULL;
}

int
main ()
//////.......

vector<string> argv;
vector<string> envp;
....
::execve (..., constchar (argv), constchar (envp));
::spawnve (..., constchar (argv), constchar (envp));

//--code--
 
A

Alf P. Steinbach

* Andrew Wingorodov:
Alf P. Steinbach said:
auto_ptr calls delete, whereas you need delete[]. Not that it matters
much in practice for a char array. But formally UB.

When the function returns, the auto_ptr calls delete. As mentioned

Try what I posted earlier, it's safe:

i got it, 10x
but i'm afraid that the vector isn't equiv to the array of poiter to chars

Oh. Well, it is.

may be this is a better way?

//--code--

class constchar
{
private:
const char** v;

public:
constchar (const std::vector<std::string>& arg_);

inline virtual ~constchar () { delete [] v; }

inline operator const char** () const { return v; }

}; //!class constchar

It's generally not a good idea to dive down to the level manual memory
management, if it can be avoided.

Not that the code won't work, but it's unsafe if used in other ways than
the example you give below, and if you then later build on your
experience that the above seemed to work and implement other classes
that way, then Mr. Murphy will most likely visit and apply his Law.

Try instead (also addressing constness issues with execve):

<code>
#include <vector>
#include <string>

int execve(const char *, char *const[], char *const[]) { return -1; }

typedef std::vector<std::string> StringVector;

std::string& zeroTerminated( std::string& s )
{
s += '\0';
s.resize( s.size() - 1 );
return s;
}

class RawPointers
{
private:
std::vector<char*> myPointers;

public:
RawPointers( StringVector& arg )
: myPointers( arg.size() + 1 )
{
for( size_t i = 0; i < arg.size(); ++i )
{
myPointers = &zeroTerminated( arg )[0];
}
}

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

void callExecVe(
std::string const& filename,
StringVector args,
StringVector env
)
{
execve( filename.c_str(), RawPointers( args ), RawPointers( env ) );
// If execution gets here, the execve call failed.
// throw whatever;
}

int main( int nArgs, char* args[] )
{
callExecVe(
"blablah",
StringVector( args, args + nArgs ),
StringVector()
);
}
//
constchar::constchar (const std::vector<std::string>& arg_)
{
v = new const char* [arg_.size()+1];
std::vector<std::string>::const_iterator i = arg_.begin();
size_t j;

for (j^=j; i != arg_.end (); ++i)

Why not write just j=0 (far more readable), and why not declare j right
there, in the innermost scope it can be declared?

And why keep incrementing both an index and and an interator?

The index suffices.

{
v[j++] = (*i).c_str() ;
}

v[j] = NULL;
}

int
main ()
//////.......

vector<string> argv;
vector<string> envp;
...
::execve (..., constchar (argv), constchar (envp));
::spawnve (..., constchar (argv), constchar (envp));

//--code--

Cheers, & hth.,

- Alf
 
C

Chris ( Val )

* Andrew Wingorodov:
i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).
how i can make its simple?
there may be ready solutions?

std::vector<string> arg;
...

std::vector<char const*> v( arg.size() );
for( size_t i = 0; i < v.size(); ++i ) { v = arg.c_str(); }
blahblah( &v[0] );


Whay go through all that when he already has what he wants
in his original vector?

const char* tmp = arg.at( n ).c_str();

Cheers,
Chris Val
 
A

Andrew Wingorodov

Alf P. Steinbach said:
Why not write just j=0 (far more readable), and why not declare j right
there, in the innermost scope it can be declared?

And why keep incrementing both an index and and an interator?

the best is the enemy of the rest (c) ;-)
my code are works, thanks for all advise
 
A

Alf P. Steinbach

* Chris ( Val ):
* Andrew Wingorodov:
i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).
how i can make its simple?
there may be ready solutions?
std::vector<string> arg;
...

std::vector<char const*> v( arg.size() );
for( size_t i = 0; i < v.size(); ++i ) { v = arg.c_str(); }
blahblah( &v[0] );


Whay go through all that when he already has what he wants
in his original vector?

const char* tmp = arg.at( n ).c_str();


Andrew wants an array of pointers to C-strings, for use as execv
argument (later down the thread I checked execv's signature and found
that there's also a const issue, and that the array should be
null-terminated, but those are just technicalities).

What you have is one pointer to a C-string.


Cheers, & hth.,

- Alf
 
C

Chris ( Val )

* Chris ( Val ):




* Andrew Wingorodov:
i have std::vector<string> arg; for dynamic program configuration.
i need get const char* argv[]; for execv(3).
how i can make its simple?
there may be ready solutions?
std::vector<string> arg;
...
std::vector<char const*> v( arg.size() );
for( size_t i = 0; i < v.size(); ++i ) { v = arg.c_str(); }
blahblah( &v[0] );

Whay go through all that when he already has what he wants
in his original vector?
const char* tmp = arg.at( n ).c_str();

Andrew wants an array of pointers to C-strings, for use as execv
argument (later down the thread I checked execv's signature and found
that there's also a const issue, and that the array should be
null-terminated, but those are just technicalities).


I see.
What you have is one pointer to a C-string.

Yes.

I thought that would be sufficient for the OP's needs,
and didn't see the necessity of an additional vector :)
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top