【问题标题】:C++, std::remove_if with std::string. Resize string by popping it's end in lambdaC++,std::remove_if 和 std::string。通过在 lambda 中弹出它的结尾来调整字符串大小
【发布时间】:2022-11-23 15:43:46
【问题描述】:

由于 std::remove 不会调整 std::string 的大小,我想出了一个解决方法:

std::string s{"aabcdef"};
std::remove_if(s.begin(), s.end(), [&s](char a)
    {
        if (a == 'a')
        {
            s.pop_back();
            return true;
        }
        return false;
    });

预期输出:bcd。实际输出:bcd。 由于某种原因,它擦除 4 个字符而不是预期的 2 个字符。如果我尝试传递一个 int 而不是计数真的在 lambda 中调用它按预期工作:

int removes{};
std::remove_if(s.begin(), s.end(), [&removes](char a)
    {
        if (a == 'a')
        {
                ++removes;
                return true;
        }
        return false;
    });
for (int i{}; i < removes; ++i) s.pop_back(); //s = "bcdef"

【问题讨论】:

  • pop_back 被调用remove_if 可以移动任何东西,而不是之后。听起来你只是想要擦除 - 删除习惯用法。您可以在 C++20 中使用 std::erase_if,或者在 C++17 或更早版本中编写您自己的等效项。
  • 为什么不直接使用从remove 返回的迭代器并将其传递给erasestd::erase(std::remove(s.begin(), s.end(), 'a')), s.end())
  • @AlanBirtles 你想要一个成员s.erase()。非成员擦除只是std::erase(s, 'a');

标签: c++ lambda iterator


【解决方案1】:

std::remove 并没有真正删除任何东西,它只是移动元素并返回范围新结束的尾后迭代器。要最终删除它们,您可以在该迭代器和字符串末尾调用 .erase() 以缩小到减小的大小。

std::string s{ "aabcdef" };

auto it = std::remove(s.begin(), s.end(), 'a');
s.erase(it, s.end());

std::cout << s << '
';

一个更简单的解决方案是简单地调用std::erase

std::string s{ "aabcdef" };
std::erase(s, 'a');

std::cout << s << '
';

输出:

bcdef

【讨论】:

    猜你喜欢
    • 2015-07-18
    • 1970-01-01
    • 2021-09-29
    • 2014-08-07
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    相关资源
    最近更新 更多