【问题标题】:Getting a substring from a std::string with iterators使用迭代器从 std::string 获取子字符串
【发布时间】:2019-03-17 17:51:58
【问题描述】:

我想从字符串中 char 的第一次出现到字符串末尾获取一个子字符串。我以为我可以只使用构造函数,就像在这个question 中一样,但它并没有真正起作用。 当我这样做时:

string(input.find(' ')+1, input.end()-1)

我面临“无构造函数”错误

error: no matching constructor for initialization of 'std::__cxx11::string' (aka 'basic_string<char>')

如何解决这个问题并让我的代码正常工作?

【问题讨论】:

  • @Yashas 任何非空字符串,其中包含 input.find 中的字符和其他一些符号,例如“堆栈溢出”
  • find 没有返回迭代器,这是你遇到的问题

标签: c++ string iterator std


【解决方案1】:

我假设inputstd::string

如果你看一下std::string::find的文档,你会发现它返回的是找到的字符的索引;不是迭代器。为了使用迭代器构造函数,你必须使用:

auto str = std::string(input.begin() + input.find(' '), input.end());

或者,您可以使用 input 的成员 substr

auto str = input.substr(input.find(' '));

您示例中的 +1 和 -1 令人困惑。如果将 1 添加到 first,那么您将获得从 找到的字符开始的子字符串,而不是从该字符开始。如果从末尾减去 1,则复制到最后一个字符之前的一个,而不是到字符串的末尾。


请注意,您可能还需要处理找不到字符的情况。构造函数方法(正如我已经实现的那样)将具有未定义的行为。 substr 方法会抛出异常。

【讨论】:

  • 您实际上不需要 substr 的第二个参数,因为您需要一直走到最后 ;)
  • @Yashas 我曾假设 OP 根据示例代码希望子字符串在结束前最多一个​​。这似乎与描述相冲突......
  • 哦,我明白了。示例代码和描述相互冲突。我认为 OP 不希望空间成为子字符串的一部分,因此您必须在传递给 substr 之前向索引添加 +1。
  • 如果没有找到空间,第一个解决方案不会是UB吗?
【解决方案2】:

std::stringfind 成员函数不返回迭代器。

还有std::string::substr,您可以将其用作input.substr(input.find(' ') + 1);

【讨论】:

  • 但是为什么我不能像我提到的那样使用构造函数?
  • 因为input.find 不返回迭代器
【解决方案3】:

为了防御性编程,您可能需要考虑input 中没有空格的病态情况。

这里有两种解决方案,一种使用迭代器和标准算法,另一种使用字符串的find方法。

#include <string>
#include <algorithm>
#include <iostream>

std::string 
all_after_space_iters(std::string const& input)
{
    auto last = input.end();

    auto after_found = [&]
    {
        auto current = std::find(input.begin(), last, ' ');
        if (current != last)
            current = std::next(current);
        return current;
    };

    return std::string(after_found(), last);
}


std::string 
all_after_space_no_iters(std::string const& input)
{
    auto pos = input.find(' ');

    auto result = std::string();
    if (pos != std::string::npos)
    {
        result = input.substr(pos + 1);
    }
    return result;
}

std::string check(std::string s)
{
    if (s.empty())
        s = "**empty**";
    return s;
}


int main()
{
    std::cout << check(all_after_space_iters("dog cat")) << '\n';
    std::cout << check(all_after_space_no_iters("dog cat")) << '\n';
    std::cout << check(all_after_space_iters("dogcat")) << '\n';
    std::cout << check(all_after_space_no_iters("dogcat")) << '\n';
}

预期输出:

cat
cat
**empty**
**empty**

http://coliru.stacked-crooked.com/a/44e484d3325d195e

注意:这些只是示例。给这只猫剥皮的方法有很多。

【讨论】:

    猜你喜欢
    • 2017-01-07
    • 2020-01-16
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 2021-01-03
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多