C++ 解释字符串修剪函数

C++ 解释字符串修剪函数,c++,string,c++11,c++14,C++,String,C++11,C++14,我遇到了下面的代码,但需要一些帮助来理解代码。假设字符串s的两边都有空格 string trim(string const& s){ auto front = find_if_not(begin(s), end(s), isspace); auto back = find_if_not(rbegin(s), rend(s), isspace); return string { front, back.base() }; } 作者指出,后面指向最后一个空格的末尾,而前面

我遇到了下面的代码,但需要一些帮助来理解代码。假设字符串s的两边都有空格

string trim(string const& s){
   auto front = find_if_not(begin(s), end(s), isspace);
   auto back = find_if_not(rbegin(s), rend(s), isspace);
   return string { front, back.base() };
}
作者指出,后面指向最后一个空格的末尾,而前面指向第一个非空白字符。所以调用了back.base(),但我不明白为什么


返回语句中字符串后面的大括号代表什么?

大括号是新的C++11初始化

.base()
和反向迭代器

.base()
用于返回基础迭代器(
back
是一个
反向迭代器
),以便从有效范围正确构造新字符串

一幅画。字符串的正常迭代器位置(关于
rend()
的工作方式,它比这稍微复杂一点,但从概念上来说…)

两个find循环完成后,此序列中这些迭代器的结果将位于:

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                ^
                              back
如果我们只使用这些迭代器并从中构造一个序列(我们不能,因为它们不匹配类型,但无论如何,假设我们可以),结果将是“从a开始复制,在D停止”,但它不会在结果数据中包含D

输入反向迭代器的
back()
成员。它返回前向迭代器类的非反向迭代器,该迭代器位于后向迭代器“旁边”的元素;i、 e

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                    ^
                               back.base()
现在,当我们复制我们的范围
{front,back.base()}
时,我们从
A
开始复制,并在第一个空格处停止(但不包括它),从而包括我们将错过的D

顺便说一句,这实际上是一段很流畅的代码

一些附加检查

在原始代码中添加了一些基本检查

为了与原始代码的精神保持一致(C++1y/C++14用法),添加了一些对空字符串和仅空白字符串的基本检查

string trim_check(string const& s)
{
  auto is_space = [](char c) { return isspace(c, locale()); };
  auto front = find_if_not(begin(s), end(s), is_space);
  auto back = find_if_not(rbegin(s), make_reverse_iterator(front), is_space);
  return string { front, back.base() };
}

值得注意的是,
base()
迭代器引用了反向迭代器引用的元素旁边的元素。在这种情况下,与std::next(back)有点同义,但不是在相反方向,而是在基础序列的“前进”方向。@WhozCraig Yes。作为一个附加参考,它包含了一篇关于
反向迭代器
的精彩文章。感谢您的评论,但是为什么前面指向第一个非空格字符,而后面不指向最后一个非空格字符?@Smithy
back
引用了最后一个非空格字符。但是,如果您将其作为副本的
end
迭代器(或者在您的例子中,迭代器范围构造函数)包含,则这是停止位置,并且您缺少一个插槽(无论如何,它是错误的迭代器类型)。你不想停在那里,你想停在那个位置之后的一个“槽”。想象一下,它类似于正常迭代器序列中的
end()
如何引用最后一个元素的“过去一次”。记住,在C++迭代器中,当你到达这里时,终点意味着停止,一旦你通过这里,就不要停止。我希望这是有意义的。我的ascii技术很蹩脚,但我希望这能给这个答案带来一个画面(=1 btw)。除了分析整个问题,这实际上看起来像一段整洁的代码。这段代码将在只包含一个或多个空白字符的输入上崩溃,因为迭代器将交叉。@j_random_hacker我同意。它需要一个安全阀来确保
back.base()
大于
front
,否则只返回空字符串。原则上我还是喜欢这个主意。我认为它实际上会抛出一个长度异常,因为
last
-
first
的结果将是负数。
string trim_check(string const& s)
{
  auto is_space = [](char c) { return isspace(c, locale()); };
  auto front = find_if_not(begin(s), end(s), is_space);
  auto back = find_if_not(rbegin(s), make_reverse_iterator(front), is_space);
  return string { front, back.base() };
}