49

I have a program that reads hard-coded file-path and I want to make it read file-path from command line instead. For that purpose I changed the code like this:

#include <iostream>

int main(char *argv[])
{
...
}

but, argv[1] variable exposed this way seems to be of type pointer, and I need it as a string. What should I do to convert this command line argument to string?

7
  • 3
    The canonical format for main is int main(int argc, char *argv[]). What you have will compile, but it will result in undefined behaviour. Commented Mar 11, 2013 at 17:24
  • I don't need arg count, just the string of representing first argument. Commented Mar 11, 2013 at 17:25
  • 6
    hmm.. std::string s(argv[1]); is that what you want to do? Commented Mar 11, 2013 at 17:25
  • 1
    @theta: It doesn't matter; it still won't work. Commented Mar 11, 2013 at 17:25
  • 1
    "It raises error when I use the program on command line." -- Feel free to be a little more specific. Commented Mar 11, 2013 at 18:06

7 Answers 7

50

It's already an array of C-style strings:

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


int main(int argc, char *argv[]) // Don't forget first integral argument 'argc'
{
  std::string current_exec_name = argv[0]; // Name of the current exec program
  std::vector<std::string> all_args;

  if (argc > 1) {
    all_args.assign(argv + 1, argv + argc);
  }
}

Argument argc is count of arguments plus the current exec file.

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

Comments

37

You can create an std::string

#include <string>
#include <vector>
int main(int argc, char *argv[])
{
  // check if there is more than one argument and use the second one
  //  (the first argument is the executable)
  if (argc > 1)
  {
    std::string arg1(argv[1]);
    // do stuff with arg1
  }

  // Or, copy all arguments into a container of strings
  std::vector<std::string> allArgs(argv, argv + argc);
}

Comments

12

No need to upvote this. It would have been cool if Benjamin Lindley made his one-liner comment an answer, but since he hasn't, here goes:

std::vector<std::string> argList(argv, argv + argc);

If you don't want to include argv[0] so you don't need to deal with the executable's location, just increment the pointer by one:

std::vector<std::string> argList(argv + 1, argv + argc);

Comments

2
#include <iostream>

std::string commandLineStr= "";
for (int i=1;i<argc;i++) commandLineStr.append(std::string(argv[i]).append(" "));

1 Comment

This would create temporary string objects for no reason at all. commandLineStr.append(argv[i]).append(" ") would be much more efficient (append returns *this to allow this chaining). Also, the default constructor will make the string blank, so the initialization is also wasteful.
2

I'm not sure if this is 100% portable but the way the OS SHOULD parse the args is to scan through the console command string and insert a nil-term char at the end of each token, and int main(int,char**) doesn't use const char** so we can just iterate through the args starting from the third argument (@note the first arg is the working directory) and scan backward to the nil-term char and turn it into a space rather than start from beginning of the second argument and scanning forward to the nil-term char. Here is the function with test script, and if you do need to un-nil-ify more than one nil-term char then please comment so I can fix it; thanks.

#include <cstdio>
#include <iostream>

using namespace std;

namespace _ {
/* Converts int main(int,char**) arguments back into a string.
@return false if there are no args to convert.
@param arg_count The number of arguments.
@param args      The arguments. */
bool ArgsToString(int args_count, char** args) {
  if (args_count <= 1) return false;
  if (args_count == 2) return true;
  for (int i = 2; i < args_count; ++i) {
    char* cursor = args[i];
    while (*cursor) --cursor;
    *cursor = ' ';
  }
  return true;
}
}  // namespace _

int main(int args_count, char** args) {
  cout << "\n\nTesting ArgsToString...\n";

  if (args_count <= 1) return 1;
  cout << "\nArguments:\n";
  for (int i = 0; i < args_count; ++i) {
    char* arg = args[i];
    printf("\ni:%i\"%s\" 0x%p", i, arg, arg);
  }
  cout << "\n\nContiguous Args:\n";
  char* end = args[args_count - 1];
  while (*end) ++end;
  cout << "\n\nContiguous Args:\n";
  char* cursor = args[0];
  while (cursor != end) {
    char c = *cursor++;
    if (c == 0)
      cout << '`';
    else if (c < ' ')
      cout << '~';
    else
      cout << c;
  }
  cout << "\n\nPrinting argument string...\n";
  _::ArgsToString(args_count, args);
  cout << "\n" << args[1];
  return 0;
}

Comments

1

It's simple. Just do this:

#include <iostream>
#include <vector>
#include <string.h>

int main(int argc, char *argv[])
{
    std::vector<std::string> argList;
    for(int i=0;i<argc;i++)
        argList.push_back(argv[i]);
    //now you can access argList[n]
}

@Benjamin Lindley You are right. This is not a good solution. Please read the one answered by juanchopanza.

5 Comments

Skip the loop and just use the vector constructor. std::vector<std::string> argList(argv, argv + argc);
That's a lot of overhead to extract one string.
@BenjaminLindley can you explain what that means? For example, if I didn't want to include argv[0], what would I change in that line? I think this is the kind of initializer being used, but I can't be certain: initializer_list<value_type> il, const allocator_type& alloc = allocator_type() : cplusplus.com/reference/vector/vector/vector
Well, my co-worker hooked me up with an answer to my specific request, at least :) std::vector<std::string> args(argv+1, argv + argc); I didn't realize the first parameter was just a pointer, ergo a single increment would be all that's needed.
@BenjaminLindley can you explain how this code works ?
1

Because all attempts to print the argument I placed in my variable failed, here my 2 bytes for this question:

std::string dump_name;

(stuff..)

if(argc>2)
{
    dump_name.assign(argv[2]);
    fprintf(stdout, "ARGUMENT %s", dump_name.c_str());
}

Note the use of assign, and also the need for the c_str() function call.

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.