Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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]) );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top