Изменить аргумент командной строки argv

Я хотел бы изменить или стереть аргумент командной строки в 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

Тем не мение, --item все еще содержится в списке.

Какой лучший способ сделать это?

4

Решение

Вы пробовали отладку? Если вы это сделаете, вы увидите, что он никогда не пытается ничего стереть.
Вы не можете сравнить строки (char*) с простым равенством, потому что в действительности вы сравниваете указатели, которые (почти) никогда не будут равны. Вместо этого вы должны использовать функции сравнения строк, например:

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

Кроме того, поскольку вы перезаписываете аргумент, вам не нужно использовать много пробелов, вы можете просто установить его в пустую строку (argv[i] = "") или измените существующую строку, чтобы она стала пустой (argv[i][0] = 0). В качестве альтернативы, вы можете сдвинуть остальные аргументы, чтобы избежать пробелов, которые могут запутать остальную часть вашего кода.

3

Другие решения

Поскольку вы используете C ++, вы можете конвертировать все ваши C-подобные строки в std :: string. Поскольку эта операция выполняется один раз в начале программы, проблем с эффективностью нет.

//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

В противном случае (избегая взлома с помощью 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);
}

Если по какой-либо причине вам все еще нужен itemFound, вы можете установить его в блоке if.

(Примечание: вам не нужны скобки, когда у вас есть блок с одним оператором, хотя это спорная тема 🙂 https://softwareengineering.stackexchange.com/questions/16528/single-statement-if-block-braces-or-no)

редактировать (заботится о существовании операторов сравнения между std :: string и 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
}
}

или же:

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]) );
1