【问题标题】:Get all values using list iterator使用列表迭代器获取所有值
【发布时间】:2019-09-30 14:26:05
【问题描述】:

我正在尝试编写命令行解析器。这是我以前使用的代码示例:

#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 键,它没有值,我不需要通过在 -l 之后添加“1”或其他内容来修改 args 列表。我无法获得最后一个键和值,因为此时 argString 是“123,abc”。如果你查看源 Java 代码,它有 hasNext() 成员函数

那么,如何重写这段代码并得到如下输出:

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

【问题讨论】:

  • 为什么--args.end()currentArgument != --args.end() 而不是简单的args.end()?是不是笔误?
  • 对不起,我错了,是的,一定是args.end()
  • key = l; value = -z 你确定这是想要的行为而不是像空字符串这样的行为吗?我猜你可能会争辩说布尔标志的值是没有意义的,但似乎这会让使用这个解析器的人感到困惑。
  • @Anzipex 1) 所以,你不清楚什么是不清楚的。您编写了代码,如果条件if (argString.at(0) == '-') 为假,它将跳出循环。 argString == "123,abc" 时就是这种情况。 2) 当代码没有按照您的预期执行时,典型的做法是:使用调试器单步执行代码,同时在每个执行步骤调查变量的值。你试过吗?
  • 为什么不推迟 currentArgument++ 部分,直到您知道参数以 - 开头?这样您就不必减少 else 中的迭代器。

标签: c++ list iterator


【解决方案1】:

正如 cmets 中所述,为什么布尔标志将下一个标志作为值有点令人困惑。您也没有提及您使用的是哪个 C++ 标准/版本。

我现在假设您的问题是算法出了什么问题?

  • 首先,break 语句跳出 for 循环(基本内容)
  • 没有中断,它也会打印出最后一个参数,但它也会一直处于循环中(因为首先递增指针然后递减它)

正如 cmets 中所述,最好先检查“-”之前 递增指针。另请注意,这里有一个 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;
}

当然,该代码没有考虑最后一个参数仅为值(无标志)的可能性。但如果需要,这很容易实现。

我希望这会有所帮助,但我鼓励您也学习如何调试代码:

  • 调试器,有一些学习曲线,但值得
  • 简单的cout的

【讨论】:

  • 我正在使用 C++11。我看到这段代码确实简化了解决方案
猜你喜欢
  • 2013-12-07
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
相关资源
最近更新 更多