解释字符串修剪功能

Smi*_*thy 21 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() };
}
Run Code Online (Sandbox Code Playgroud)

作者说,后面指向最后一个空格的末尾,而前面指向第一个非空白字符.所以back.base()被调用但我不明白为什么.

另外,在return语句中跟随字符串的花括号是什么?

Nia*_*all 28

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

.base() 并反转迭代器

.base()是回去的底层迭代器(backreverse_iterator),以正确构建从有效范围内新的字符串.

照片.字符串的正常迭代器位置(关于它是如何rend()工作的,它比这更复杂,但概念上无论如何......)

        begin                                 end
          v                                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
      ^                                   ^
    rend                                rbegin
Run Code Online (Sandbox Code Playgroud)

一旦你的两个find循环完成,这个序列中的迭代器的结果将定位在:

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                ^
                              back
Run Code Online (Sandbox Code Playgroud)

是我们采取只是那些迭代器,并从中构建一个序列(我们不能,因为他们不匹配的类型,但无论如何,我们应该可以),结果将是"拷贝从A开始,停在d" 但它不包括在d得到的数据.

输入back()反向迭代器的成员.它返回一个前向迭代器类的非反向迭代器,它位于后迭代器"旁边"的元素上; 即

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                    ^
                               back.base()
Run Code Online (Sandbox Code Playgroud)

现在当我们复制我们的范围时,{ 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() };
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是`base()`迭代器引用了反向迭代器引用的*旁边的元素*.在这种情况下,有点与`std :: next(back)`同义,但不是在反向,而是在基础序列的"向前"方向. (2认同)
  • @WhozCraig是的.作为一个额外的参考,http://en.cppreference.com/w/cpp/iterator/reverse_iterator包含了对`reverse_iterator`的一个很好的写作. (2认同)
  • 我的ascii艺术非常la脚,但我希望对此答案有一个了解(= 1 btw)。 (2认同)