vector<string> to char*[]

Discussion in 'C++' started by Andrew Wingorodov, Oct 2, 2007.

  1. 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?

    --
    www.andr.ca
    Andrew Wingorodov, Oct 2, 2007
    #1
    1. Advertising

  2. * 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


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Oct 2, 2007
    #2
    1. Advertising

  3. On Tue, 2 Oct 2007 06:09:22 +0000 (UTC), Andrew Wingorodov wrote:
    > 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;

    --
    Joel Yliluoma - http://bisqwit.iki.fi/
    : comprehension = 1 / (2 ^ precision)
    Joel Yliluoma, Oct 2, 2007
    #3
  4. Joel Yliluoma <> wrote:
    > 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();
    }

    --
    www.andr.ca
    Andrew Wingorodov, Oct 2, 2007
    #4
  5. * Andrew Wingorodov:
    > Joel Yliluoma <> wrote:
    >> 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: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Oct 2, 2007
    #5
  6. Alf P. Steinbach <> wrote:
    > 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--

    --
    www.andr.ca
    Andrew Wingorodov, Oct 2, 2007
    #6
  7. * Andrew Wingorodov:
    > Alf P. Steinbach <> wrote:
    >> 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()
    );
    }
    </code>


    > //
    > 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


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Oct 2, 2007
    #7
  8. On Oct 2, 4:33 pm, "Alf P. Steinbach" <> wrote:
    > * 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
    Chris ( Val ), Oct 2, 2007
    #8
  9. Alf P. Steinbach <> wrote:
    >
    > 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

    --
    www.andr.ca
    Andrew Wingorodov, Oct 2, 2007
    #9
  10. * Chris ( Val ):
    > On Oct 2, 4:33 pm, "Alf P. Steinbach" <> wrote:
    >> * 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

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Oct 2, 2007
    #10
  11. On Oct 3, 12:52 am, "Alf P. Steinbach" <> wrote:
    > * Chris ( Val ):
    >
    >
    >
    >
    >
    > > On Oct 2, 4:33 pm, "Alf P. Steinbach" <> wrote:
    > >> * 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 :)

    --
    Chris Val
    Chris ( Val ), Oct 2, 2007
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. pmatos
    Replies:
    6
    Views:
    23,720
  2. lovecreatesbeauty
    Replies:
    1
    Views:
    1,002
    Ian Collins
    May 9, 2006
  3. Replies:
    8
    Views:
    1,887
    Csaba
    Feb 18, 2006
  4. Javier
    Replies:
    2
    Views:
    541
    James Kanze
    Sep 4, 2007
  5. Rushikesh Joshi
    Replies:
    0
    Views:
    343
    Rushikesh Joshi
    Jul 10, 2004
Loading...

Share This Page