Получить все значения с помощью итератора списка - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь написать анализатор командной строки. Вот пример кода, который я использовал для:

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

int main() {
    std::list<std::string> args;
    args.push_back("-l");
    args.push_back("-z");
    args.push_back("123,abc");
    args.push_back("-d");
    args.push_back("/dev/null");

    std::list<std::string>::iterator currentArgument;

    for (currentArgument = args.begin(); currentArgument != args.end();) {
        const std::string argString = *currentArgument++;
        if (argString.at(0) == '-') {
                std::cout << "key = " << argString.substr(1) << std::endl;
                std::cout << "value = " << *currentArgument << std::endl;
            } else {
                --currentArgument;
                break;
            }
        }
};

Результат:

key = l
value = -z
key = z
value = 123,abc

Я попытался переписать исходный код, как в примере на Java: Args.java (метод parseArgumentStrings)

Проблема в ключе bool -l, у него нет значения, и мне не нужно изменять список аргументов, добавляя «1» после -l или что-то еще. Я не могу получить последний ключ и значение, потому что argString в этот момент равен «123, abc». Если вы посмотрите на исходный код Java, он имеет функцию-член hasNext ()

Итак, как переписать этот код и получить вывод, подобный следующему:

key = l
value = -z
key = z
value = 123,abc
key = d
value = /dev/null

1 Ответ

1 голос
/ 01 октября 2019

Как уже говорилось в комментариях, немного сбивает с толку, почему логический флаг будет иметь следующий флаг в качестве значения. Вы также не упомянули, какой стандарт / версию C ++ вы используете.

Теперь я предполагаю, что ваш вопрос в том, что не так с алгоритмом?

  • Во-первых, оператор break выпадает из цикла for (основной материал)
  • без перерыва он также распечатает последний аргумент, но он также останется в цикле навсегда (начиная с первого увеличивающего указателя, а затем уменьшающего его)

Как указано в комментариях, он будетлучше сначала проверить «-», прежде чем увеличивать указатель. Также обратите внимание, что существует std :: next, который можно использовать здесь.

Я не уверен, что этот список (внутренне двойной связанный список) является лучшим контейнером здесь.

Если мыПредположим, что логический флаг не должен выводить значение, код может выглядеть следующим образом:

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

int main() {
    std::vector<std::string> args;
    args.push_back("-l");
    args.push_back("-z");
    args.push_back("123,abc");
    args.push_back("-d");
    args.push_back("/dev/null");

    for (auto it = std::begin(args); it != std::end(args); ++it) {
        if ((*it).at(0) == '-') {
            std::cout << "key = " << (*it).substr(1) << std::endl;
            auto next = std::next(it);
            if ((*next).at(0) == '-'){
                continue;
            }else{
                std::cout << "value = " << *(++it) << std::endl;
            }
        }
    }
    return 0;
}

Конечно, этот код не учитывает возможность того, что последний аргумент может быть только значением (без флага). Но это легко реализовать, если необходимо.

Я надеюсь, что это помогает, но я призываю вас также научиться отлаживать код:

  • отладчик, имеет некоторую кривую обучения, но этоСтоит
  • простой кут
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...