5

So I want to pass arguments to following function

execve(char *filename, char *argv[], char *envp[])

currently my argv[] is a string array. I want to convert it into a char* array so I can pass it to this function.

I have looked around and found many ways to convert a string to a char array but how to convert a string array to an array of char array I guess would be the right term Any help?

3
  • 2
    By string array, do you mean something like string myargs[5]; and you want to pass that to execve? Commented Sep 29, 2013 at 20:06
  • char *argv[] is actually an array of char* elements. Each element in the array points to a char* string. Therefore argv[0] is a char* string that may be printed/used. Commented Sep 29, 2013 at 20:09
  • @us2012 yes by a string array i mean an array of strings like string myargs[5] Commented Sep 29, 2013 at 20:10

2 Answers 2

7

You'll need to get the address of the data inside your std::strings. Note, that these are not required to be null-terminated, i.e., you'll need to make sure that all strings are null terminated. Also, the array passed as argv also needs to have the last element to be a null pointer. You could use code along the lines of this:

std::string array[] = { "s1", "s2" };
std::vector<char*> vec;
std::transform(std::begin(array), std::end(array),
               std::back_inserter(vec),
               [](std::string& s){ s.push_back(0); return &s[0]; });
vec.push_back(nullptr);
char** carray = vec.data();

When compiling with C++03, there are some changes necessary:

  1. Instead of using the lambda expression, you need to create a suitable function or function object doing the same transformation.
  2. Instead of using nullptr you need to use 0.
  3. In C++03 std::string is not guaranteed to be contiguous, i.e., you need an additional, auxiliary std::vector<char> to hold a contiguous sequence of characters.
  4. There are no functions begin() and end() deducing the size of an array but they can easily be implemented in C++03:

    template <typename T, int Size> T* begin(T (&array)[Size]) { return array; }
    template <typename T, int Size> T* end(T (&array)[Size]) { return array + Size; }
    
  5. The C++03 std::vector<T> doesn't have a data() member, i.e., you also need to take the address of the first element.

Sign up to request clarification or add additional context in comments.

15 Comments

do i need to include any libraries these are the errors i am getting ‘transform’ is not a member of ‘std’ ‘begin’ is not a member of ‘std’ error: ‘end’ is not a member of ‘std’ warning: lambda expressions only available with -std=c++0x or -std=gnu++0x [enabled by default] ‘nullptr’ was not declared in this scope
You need to compile with the C++11 option or use a function object instead of the lambda expression and 0 instead of nullptr. Of course, you need to include the relevant standard headers, too (in this case <algorithm>, <iterator>, <string>, and <vector>).
i have included vector and iostream and used using namespace std
even after including <iterator> i am still getting 'begin' and 'end' is not a member of 'std' .. I am using g++ on ubuntu 12.04
@user2557844: I guess, you are compiling without -std=c++11 or -std=c++0x. In this case you might need to define a begin() and end() function.
|
0

The following worked for me:

const char *argv[]{"-l", nullptr};
execvp("ls", const_cast<char**>(argv));

Since they are string literals, you don't need to null-terminate them, but you still need the null string at the end of the array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.