【问题标题】:trim matching characters from start or end of string c++从字符串c ++的开头或结尾修剪匹配的字符
【发布时间】:2017-09-28 23:03:52
【问题描述】:

我需要修剪字符串的开头结尾,给定一个匹配的字符。

我的函数定义看起来:

void trim(std::string &s, char c, bool reverse = false);

bool reverse 标记是否修剪字符串的开头 (false) 或结尾 (true)。

例如:

s = "--myarg--";
trim(s, '-', false); // should set s to "myarg--"
trim(s, '-', true);  // should set s to "--myarg"

要修剪开头(即reverse=false),这可以正常工作:

bool ok = true;
auto mayberemove = [&ok](std::string::value_type ch){if (ch != '-') ok = false; return ok;};
s.erase(std::remove_if(s.begin(), s.end(), mayberemove), s.end());

lambda 只为每个匹配“-”的字符返回 true,直到第一次出现不匹配的字符,然后继续返回 false。在这里,我将匹配的字符硬编码为“-”,以使代码更易于阅读。

我遇到的麻烦是反向修剪。这不起作用 - 与上面相同,但使用反向迭代器和 ::base():

s.erase(std::remove_if(s.rbegin(), s.rend(), mayberemove).base(), s.end());

相反,上面的行会修剪除前两个之外的所有结尾字符。

有什么想法吗? 谢谢

【问题讨论】:

  • 不应该太难你把所有这些都塞进minimal reproducible example。现在你说你遇到了反向问题,但只提供了一个类似的反向代码。
  • 这个答案可能有用(允许左右修剪)stackoverflow.com/questions/216823/…
  • @rici 不起作用。我看不到 remove 有那个结构,如果有,它会从整个字符串中删除所有“-”字符——这不是我想要的。
  • @blair:好的,没错。你真正想要使用的是find_if_not)。
  • 您不应将bool 用于反向参数。它使代码更难理解。请改用enum class 或使用trimtrim_lefttrim_right 等多个函数。如果还不相信,请阅读有关良好编码实践的书籍。

标签: c++


【解决方案1】:
std::string& trim( std::string& s, char c, bool reverse = false )
{
  return reverse
    ? s.erase( s.find_last_not_of( c ) + 1 )
    : s.erase( 0, s.find_first_not_of( c ) );
}

【讨论】:

  • 函数定义为返回void
  • @Mark 实际上,除了返回之外,它确实有效。我只是用一堆“-”来测试它。
  • 我可能会选择这个。我以前没见过这些功能。它似乎非常简洁,我猜效率很高。
  • @BlairFonville 是的,一开始没仔细看,其实很简单,很聪明。
  • 是的,哎呀,我总是使用比这更强大的版本,并将其硬塞到 OP 的函数签名中。感谢返回类型编辑标记!
【解决方案2】:

嗯,其实我只是想通了。看起来我需要为相反的情况反转 mayberemove lambda 的逻辑。所以,这似乎工作正常:

if (reverse) {
    bool notok = false;
    auto mayberemove = [&notok](std::string::value_type ch){if (ch != '-') notok = true; return notok;};
    s.erase(std::remove_if(s.rbegin(), s.rend(), mayberemove).base(), s.end());
}
else {
    bool ok = true;
    auto mayberemove = [&ok](std::string::value_type ch){if (ch != '-') ok = false; return ok;};
    s.erase(std::remove_if(s.begin(), s.end(), mayberemove),s.end());
}

这行得通。现在我只需要了解原因。

【讨论】:

  • 或者,你可以在reverse = true时使用s.erase(s.begin(), std::remove_if(s.rbegin(), s.rend(), mayberemove).base())
  • 添加if (notok) { cout << 'r';} cout << ch; 之类的内容是更好地了解正在发生的事情的好方法。正确执行此操作,相同的 lambda 应该适用于两者。我在想[&ok](char ch) { if (ch != '-') { ok = false; } return ok; };
  • 也就是说,这可能比您需要做的工作多得多,因为它总是扫描整个字符串,即使它的工作几乎总是很早就完成了。
  • @user4581301 我也这么认为。它效率不高,但我只是想让它为我自己的教化而工作。
  • 跟我想的差不多。朝着错误的方向前进,您仍然会学到一些以后可以应用的东西。通常是,“好吧,我不会再那样做了!”但有一些宝石。
猜你喜欢
  • 2011-03-01
  • 1970-01-01
  • 2021-11-06
  • 2013-08-18
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多