Explaining a string trimming function

后端 未结 1 1651
既然无缘
既然无缘 2021-02-07 01:09

I came across the code below but need some help with understanding the code. Assume that the string s has spaces either side.

string trim(string const& s){
         


        
相关标签:
1条回答
  • 2021-02-07 01:34

    The braces are the new C++11 initialisation.

    .base() and reverse iterators

    The .base() is to get back the the underlying iterator (back is a reverse_iterator), to properly construct the new string from a valid range.

    A picture. Normal iterator positions of a string (it is a little more complex than this regarding how rend() works, but conceptually anyway...)

            begin                                 end
              v                                    v
            -------------------------------------
            | sp | sp | A | B | C | D | sp | sp |
            -------------------------------------
          ^                                   ^
        rend                                rbegin
    

    Once your two find loops finish, the result of those iterators in this sequence will be positioned at:

                      front
                        v
            -------------------------------------
            | sp | sp | A | B | C | D | sp | sp |
            -------------------------------------
                                    ^
                                  back
    

    Were we to take just those iterators and construct a sequence from them (which we can't, as they're not matching types, but regardless, supposed we could), the result would be "copy starting at A, stopping at D" but it would not include D in the resulting data.

    Enter the back() member of a reverse iterator. It returns a non-reverse iterator of the forward iterator class, that is positioned at the element "next to" the back iterator; i.e.

                      front
                        v
            -------------------------------------
            | sp | sp | A | B | C | D | sp | sp |
            -------------------------------------
                                        ^
                                   back.base()
    

    Now when we copy our range { front, back.base() } we copy starting at A and stopping at the first space (but not including it), thereby including the D we would have missed.

    Its actually a slick little piece of code, btw.

    Some additional checking

    Added some basic checks to the original code.

    In trying to keeping with the spirit of the original code (C++1y/C++14 usage), adding some basic checks for empty and white space only strings;

    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() };
    }
    
    0 讨论(0)
提交回复
热议问题