tcffm
tcffm

Reputation: 149

C++ Pointer to Pointer to chars in String-Array

I have to test the function

std::vector<std::string> convert_arguments(int argc, char **argv) {
[some code]
return command_arguments;
};

that takes a pointer to an array of command arguments and returns a Vector containing those arguments. The function works well. But I'm having trouble constructing such a pointer myself. The array is an array of strings, i.e. an array of array of chars. As far as I know, the pointer is supposed to point to the first pointer of the pointers pointing to the first letters of the strings (that sounds quite strange). What I need is an exemplary pointer **argv that I can pass to the function to see if it works. I know that there are a lot of similar questions on the internet, but I couldn't really find an answer that works for me. I would be very thankful if you could help me out, because I've been looking for an answer for several hours.

Upvotes: 1

Views: 540

Answers (5)

Antonin GAVREL
Antonin GAVREL

Reputation: 11219

You can achieve this with a pointer of char arrays in the C fashion:

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

using namespace std;

// borrowed from prehistoricpenguin
std::vector<std::string> convert_arguments(int argc, const char **argv) {
  return std::vector<std::string>(argv + 1, argv + argc);
}

bool test1(void) {
    int argc = 5;
    const char *argv[] = {"program_name", "some string", "another", "command", "ok", NULL };
    std::vector<std::string> myexpectedvector =  {"some string", "another","command", "ok" };
    std::vector<std::string> s = convert_arguments(argc, argv);
    return (s == myexpectedvector);
}

int main () {
    std::cout << test1() << std::endl;
}

Upvotes: 0

prehistoricpenguin
prehistoricpenguin

Reputation: 6326

A one-line version:

std::vector<std::string> convert_arguments(int argc, const char **argv) {
  return std::vector<std::string>(argv + 1, argv + argc);
}

Or even simpler with c++11 above

std::vector<std::string> convert_arguments(int argc, const char **argv) {
  return {argv + 1, argv + argc};
}

Explanation:

We call the constructor for std::vector with two iterator ranges(pointer can be treat as an iterator), since argv is a pointer arry, the left range is argv+1, the right range is argv + argc.

For the std::string constructor, the const char* is passed.

Upvotes: 0

Serge Ballesta
Serge Ballesta

Reputation: 148880

The command line arguments use both conventions to pass the number of arguments:

  • it is explicitely passed in argc
  • the argv array contains a null pointer as its last (useful) element

As you can construct a string for a const char *, code can be as simple as:

std::vector<std::string> convert_arguments(int argc, char **argv) {
    std::vector<std::string> command_arguments;
    for (int i=0; i<argc; i++) {
        command_arguments.push_back(std::string(argv[i]));
    }
    return command_arguments;
}

or (second convention):

std::vector<std::string> convert_arguments(int argc, char **argv) {
    std::vector<std::string> command_arguments;
    for (const char **ix=argv; ix!=nullptr; ix++) {
        command_arguments.push_back(std::string(*ix++));
    }
    return command_arguments;
}

If you want to build such an array for tests, you can easily do it from literal strings:

const char *const_argv[] = { "foo", "fee", "bar", "baz", nullptr};  // add the last null
int my_argc = sizeof(my_argv)/sizeof(*my_argv) - 1;        // but do no count it
char ** my_argv = const_cast<char **>(const_argv);         // cast it

Beware: This code correctly declared const_argv to be an array of pointers to const characters, because a string literal is const, and uses const_cast to be able to pass it to above function. It is harmless because the function never try to change its parameters but the rule is that const_cast should be avoided if possible.

If you really need an array of non const strings, you must build the strings first and then the array:

char a1[] = "foo";
char a2[] = "fee";
char a3[] = "bar";
char a4[] = "baz";
char *argv[] = {a1, a2, a3, a4, nullptr};

Upvotes: 2

ACB
ACB

Reputation: 1637

char** argv is really just a 2 dimensional array. You can create such an array via char** argv = new char*[argc];. Then you can just loop over the argv array with for(int i=0;i < argc; ++i) and assaign whatever string you want to each entry.

Upvotes: 2

Sushant Shelte
Sushant Shelte

Reputation: 1

Here the argc stores number of arguments passed and argv stored all the arguments. You can do something like,

std::vector<std::string> vec;
for (int counter=1;counter<argc;counter++)   //0th argument is the program name
{
    vec.push_back(argv[counter]); //push each string into vector
}
return vec;

Upvotes: 0

Related Questions