4

I would like to modify or erase a command-line argument in argv.

//Somewhere near the top of main()

bool itemFound(false);
for(int i=1; i<argc; ++i) {
  if(argv[i] == "--item") {
    itemFound = true;
    //And remove this item from the list
    argv[i] = "      ";   //Try to remove be just inserting spaces over the arg
  }
}

//Now, use argc/argv as normal, knowing that --item is not in there

However, --item is still contained in the list.

What's the best way to do this?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Madeleine P. Vincent
  • 3,361
  • 5
  • 25
  • 30

2 Answers2

3

Did you try debugging? If you do, you will see that it never attempts to erase anything. You can't compare strings (char*) with simple equality, because in reality you're comparing pointers, which will (almost) never be equal. Instead, you should use string comparison functions, like this:

if (!strcmp(argv[i], "--item")) {

Also, since you're overwriting the argument, you don't need to use a lot of spaces, you can simply set it to an empty string (argv[i] = ""), or modify the existing string to make it empty (argv[i][0] = 0). Alternatively, you could shift the rest of the arguments so you don't end up with gaps which could confuse the rest of your code.

riv
  • 6,846
  • 2
  • 34
  • 63
  • Yes riv, that was certainly my problem. Thanks. – Madeleine P. Vincent Jun 17 '13 at 09:57
  • 1
    As written, the test is very confusing, since `strcmp` returns an `int`, and not a `bool`. Far better would be `if ( strcmp( argv[i], "--item" ) == 0 )`. – James Kanze Jun 17 '13 at 10:11
  • 1
    Also, according to the C standard, `argv[i] = ""` is undefined behavior. (The C++ standard doesn't say whether you can modify `argv[i]` or not, but one would assume C compatibility here.) I don't know the why of this restriction, and I've never heard of a system where it would actually cause problems, but the C standard explicitly says that it is forbidden. – James Kanze Jun 17 '13 at 10:13
1

Since you are using C++, you could convert all your C-like strings in std::string. Since this operation is done once at the beginning of the program, there is no efficiency problem.

//Somewhere near the top of main()

bool itemFound(false);
for(int i=1; i<argc; ++i) {
  if(std::string(argv[i]) == std::string("--item") ) {
    itemFound = true;
    //And remove this item from the list
    argv[i][0] = 0;   //Transform it in an empty string, putting null as first character
  }
}

//Now, use argc/argv as normal, knowing that --item is not in there

Otherwise (avoiding hacking with argv):

std::vector<std::string> validArgs;
validArgs.reserve(argc); //Avoids reallocation; it's one or two (if --item is given) too much, but safe and not pedentatic while handling rare cases where argc can be zero
for(int i=1; i<argc; ++i) {
  const std::string myArg(argv[i]);
  if(myArg != std::string("--item") )
    validArgs.push_back(myArg);
}

If for any reason you still need itemFound you can set it in the if block.

(Note: you do not need braces when you have a block with a single statement, although this is a battled topic :) https://softwareengineering.stackexchange.com/questions/16528/single-statement-if-block-braces-or-no)

Edit (taking care of existence of comparison operators between std::string and char*)

bool itemFound(false);
for(int i=1; i<argc; ++i) {
  if(std::string("--item") == argv[i] ) {
    itemFound = true;
    //And remove this item from the list
    argv[i][0] = 0;   //Transform it in an empty string, putting null as first character
  }
}

or:

std::vector<std::string> validArgs;
validArgs.reserve(argc); //Avoids reallocation; it's one or two (if --item is given) too much, but safe and not pedentatic while handling rare cases where argc can be zero
for(int i=1; i<argc; ++i)
  if(std::string("--item") != argv[i] )
    validArgs.push_back(std::string(argv[i]) );
Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • http://coliru.stacked-crooked.com/view?id=f1448c0569a547cd366cdae779d59ab1-f674c1a6d04c632b71a62362c0ccfc51 is interesting, though I'm not certain it's "better" – Mooing Duck Jun 18 '13 at 21:33