A Better Way?

Discussion in 'C++' started by Mike Copeland, Mar 8, 2013.

  1. Is there a better way (less code, less convoluted, etc.) to access
    the last character of a string variable than this?:

    if(str2.at(str2.length()-1) != '/') str2 +="/";
     
    Mike Copeland, Mar 8, 2013
    #1
    1. Advertising

  2. On 3/8/2013 4:21 PM, Mike Copeland wrote:
    > Is there a better way (less code, less convoluted, etc.) to access
    > the last character of a string variable than this?:
    >
    > if(str2.at(str2.length()-1) != '/') str2 +="/";
    >


    Try 'back' member function:

    if (str2.back() != '/') str2 += '/';

    And, RTFM.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 8, 2013
    #2
    1. Advertising

  3. Mike Copeland

    Balog Pal Guest

    On 3/8/2013 10:21 PM, Mike Copeland wrote:
    > Is there a better way (less code, less convoluted, etc.) to access
    > the last character of a string variable than this?:
    >
    > if(str2.at(str2.length()-1) != '/') str2 +="/";


    I have a function with equivalent of that called MakeEndWith.
     
    Balog Pal, Mar 8, 2013
    #3
  4. Mike Copeland

    Balog Pal Guest

    On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    > On 3/8/2013 4:21 PM, Mike Copeland wrote:
    >> Is there a better way (less code, less convoluted, etc.) to access
    >> the last character of a string variable than this?:
    >>
    >> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>

    >
    > Try 'back' member function:
    >
    > if (str2.back() != '/') str2 += '/';


    But only if you're sure the string is not empty...
     
    Balog Pal, Mar 8, 2013
    #4
  5. On 3/8/2013 6:36 PM, Balog Pal wrote:
    > On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    >> On 3/8/2013 4:21 PM, Mike Copeland wrote:
    >>> Is there a better way (less code, less convoluted, etc.) to access
    >>> the last character of a string variable than this?:
    >>>
    >>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>>

    >>
    >> Try 'back' member function:
    >>
    >> if (str2.back() != '/') str2 += '/';

    >
    > But only if you're sure the string is not empty...


    If it's not empty, what would .at(-1) do?

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 9, 2013
    #5
  6. On 09.03.2013 00:36, Balog Pal wrote:
    > On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    >> On 3/8/2013 4:21 PM, Mike Copeland wrote:
    >>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>>

    >>
    >> Try 'back' member function:
    >>
    >> if (str2.back() != '/') str2 += '/';

    >
    > But only if you're sure the string is not empty...


    This applies to the first code as well.


    Marcel
     
    Marcel Müller, Mar 9, 2013
    #6
  7. Mike Copeland

    Balog Pal Guest

    On 3/9/2013 3:23 AM, Victor Bazarov wrote:
    > On 3/8/2013 6:36 PM, Balog Pal wrote:
    >> On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    >>> On 3/8/2013 4:21 PM, Mike Copeland wrote:
    >>>> Is there a better way (less code, less convoluted, etc.) to access
    >>>> the last character of a string variable than this?:
    >>>>
    >>>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>>>
    >>>
    >>> Try 'back' member function:
    >>>
    >>> if (str2.back() != '/') str2 += '/';

    >>
    >> But only if you're sure the string is not empty...

    >
    > If it's not empty, what would .at(-1) do?


    Nothing we'd like. So an extra score to make it a function that does the
    thing right, and brings the info in its name. Instead of pasting around
    expressions that may be bad part of the time and in any case take more
    toll on reading.
     
    Balog Pal, Mar 9, 2013
    #7
  8. Mike Copeland

    Öö Tiib Guest

    On Saturday, 9 March 2013 11:30:07 UTC+2, Balog Pal wrote:
    > On 3/9/2013 3:23 AM, Victor Bazarov wrote:
    > > On 3/8/2013 6:36 PM, Balog Pal wrote:
    > >> On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    > >>> On 3/8/2013 4:21 PM, Mike Copeland wrote:
    > >>>> Is there a better way (less code, less convoluted, etc.) to access
    > >>>> the last character of a string variable than this?:
    > >>>>
    > >>>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    > >>>
    > >>> Try 'back' member function:
    > >>>
    > >>> if (str2.back() != '/') str2 += '/';
    > >>
    > >> But only if you're sure the string is not empty...

    > >
    > > If it's not empty, what would .at(-1) do?

    >
    > Nothing we'd like. So an extra score to make it a function that does the
    > thing right, and brings the info in its name. Instead of pasting around
    > expressions that may be bad part of the time and in any case take more
    > toll on reading.


    Was it for file paths? Use a library that deals with file paths (like
    boost::filesystem). Was it for URIs? Some network/uri was even proposed
    into std I think. If there is need to morph some dirty user-entered
    string into path (or URI) then use std regex stuff.

    On any case suppress that urge to invent a square wheel again. ;)
     
    Öö Tiib, Mar 9, 2013
    #8
  9. Mike Copeland

    Rui Maciel Guest

    Victor Bazarov wrote:

    >> But only if you're sure the string is not empty...

    >
    > If it's not empty, what would .at(-1) do?


    Adding a bug doesn't justify adding other bugs.


    Rui Maciel
     
    Rui Maciel, Mar 9, 2013
    #9
  10. Mike Copeland

    Rui Maciel Guest

    Mike Copeland wrote:

    > Is there a better way (less code, less convoluted, etc.) to access
    > the last character of a string variable than this?:
    >
    > if(str2.at(str2.length()-1) != '/') str2 +="/";


    It may not be as concise, but here's a suggestion:

    <code>
    #include <string>
    #include <iostream>

    void foo(std::string &text, std::string::value_type const c)
    {
    if( text.empty() || *(--text.end()) != c)
    {
    text += c;
    }
    }


    int main(void)
    {
    using namespace std;

    string text = "this is a string";

    cout << "string: \"" << text << "\"" << endl;

    foo(text, '/');

    cout << "string: \"" << text << "\"" << endl;

    return 0;
    }
    </code>


    Rui Maciel
     
    Rui Maciel, Mar 9, 2013
    #10
  11. On 3/9/2013 7:02 AM, Rui Maciel wrote:
    > Victor Bazarov wrote:
    >
    >>> But only if you're sure the string is not empty...

    >>
    >> If it's not empty, what would .at(-1) do?

    >
    > Adding a bug doesn't justify adding other bugs.


    Huh? With partial code posted the replacement code correctness is only
    required to be as that of the original code. With the original code the
    assumption is that the string is not empty. Based on the same
    assumption the new code is proposed. Assuming that the original code
    does NOT have a bug is no worse than assuming that the original code
    DOES have a bug. So, there.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 9, 2013
    #11
  12. Mike Copeland

    Luca Risolia Guest

    On 09/03/2013 03:23, Victor Bazarov wrote:
    > On 3/8/2013 6:36 PM, Balog Pal wrote:
    >> On 3/8/2013 10:41 PM, Victor Bazarov wrote:
    >>> On 3/8/2013 4:21 PM, Mike Copeland wrote:
    >>>> Is there a better way (less code, less convoluted, etc.) to access
    >>>> the last character of a string variable than this?:
    >>>>
    >>>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>>>
    >>>
    >>> Try 'back' member function:
    >>>
    >>> if (str2.back() != '/') str2 += '/';

    >>
    >> But only if you're sure the string is not empty...

    >
    > If it's not empty, what would .at(-1) do?


    When the string is empty, .at(-1) throws std::eek:ut_of_range, while
    ..back() is undefined behaviour (which results in a crash if you are lucky).
     
    Luca Risolia, Mar 9, 2013
    #12
  13. Mike Copeland

    Öö Tiib Guest

    On Saturday, 9 March 2013 15:08:40 UTC+2, Victor Bazarov wrote:
    > On 3/9/2013 7:02 AM, Rui Maciel wrote:
    > > Victor Bazarov wrote:
    > >> On 3/8/2013 6:36 PM, Balog Pal wrote:
    > >>> But only if you're sure the string is not empty...
    > >> If it's not empty, what would .at(-1) do?

    > > Adding a bug doesn't justify adding other bugs.

    >
    > Huh? With partial code posted the replacement code correctness is only
    > required to be as that of the original code. With the original code the
    > assumption is that the string is not empty.


    basic_string<3>::at(-1) throws out_of_range that is well-defined behavior.
    I usually avoid catching it without rethrowing so it crashes. So for
    me it does not matter and original code was defective.

    basic_string<3>::back() on empty string is guaranteed to *not* throw.
    Otherwise it is undefined behavior. In most modern implementations
    it seems to crash too.

    It is about different shades of dark of pots and kettles.
     
    Öö Tiib, Mar 9, 2013
    #13
  14. Mike Copeland

    Balog Pal Guest

    On 3/9/2013 1:10 PM, Rui Maciel wrote:
    > if( text.empty() || *(--text.end()) != c)


    Uh, the last part really should be back() or at least *rbegin()
     
    Balog Pal, Mar 9, 2013
    #14
  15. Mike Copeland

    Luca Risolia Guest

    On 08/03/2013 22:21, Mike Copeland wrote:
    > Is there a better way (less code, less convoluted, etc.) to access
    > the last character of a string variable than this?:
    >
    > if(str2.at(str2.length()-1) != '/') str2 +="/";


    str2 = std::regex_replace(str2, std::regex("[^/]$|^$"), "$&/");

    If str2 is originally empty, then it will result in "/".
     
    Luca Risolia, Mar 9, 2013
    #15
  16. Mike Copeland

    Luca Risolia Guest

    On 09/03/2013 15:03, Öö Tiib wrote:
    > On Saturday, 9 March 2013 15:08:40 UTC+2, Victor Bazarov wrote:
    >> On 3/9/2013 7:02 AM, Rui Maciel wrote:
    >>> Victor Bazarov wrote:
    >>>> On 3/8/2013 6:36 PM, Balog Pal wrote:
    >>>>> But only if you're sure the string is not empty...
    >>>> If it's not empty, what would .at(-1) do?
    >>> Adding a bug doesn't justify adding other bugs.

    >>
    >> Huh? With partial code posted the replacement code correctness is only
    >> required to be as that of the original code. With the original code the
    >> assumption is that the string is not empty.

    >
    > basic_string<3>::at(-1) throws out_of_range that is well-defined behavior.
    > I usually avoid catching it without rethrowing so it crashes. So for
    > me it does not matter and original code was defective.
    >
    > basic_string<3>::back() on empty string is guaranteed to *not* throw.
    > Otherwise it is undefined behavior. In most modern implementations
    > it seems to crash too.
    >
    > It is about different shades of dark of pots and kettles.


    Not handling an exception is not undefined behaviour though.
     
    Luca Risolia, Mar 9, 2013
    #16
  17. Mike Copeland

    Rui Maciel Guest

    Balog Pal wrote:

    > Uh, the last part really should be back() or at least *rbegin()


    True.


    Rui Maciel
     
    Rui Maciel, Mar 9, 2013
    #17
  18. Mike Copeland

    Rui Maciel Guest

    Victor Bazarov wrote:

    > Huh? With partial code posted the replacement code correctness is only
    > required to be as that of the original code. With the original code the
    > assumption is that the string is not empty. Based on the same
    > assumption the new code is proposed. Assuming that the original code
    > does NOT have a bug is no worse than assuming that the original code
    > DOES have a bug. So, there.


    Commendable effort.


    Rui Maciel
     
    Rui Maciel, Mar 9, 2013
    #18
  19. Mike Copeland

    Luca Risolia Guest

    On 10/03/2013 00:57, Juha Nieminen wrote:
    > Luca Risolia <> wrote:
    >> On 08/03/2013 22:21, Mike Copeland wrote:
    >>> Is there a better way (less code, less convoluted, etc.) to access
    >>> the last character of a string variable than this?:
    >>>
    >>> if(str2.at(str2.length()-1) != '/') str2 +="/";

    >>
    >> str2 = std::regex_replace(str2, std::regex("[^/]$|^$"), "$&/");

    >
    > Is this an attempt to come up with the most convoluted and least
    > efficient solution to the problem as you can?


    It's a great benefit to get familiar with regular expressions (which are
    not specific to C++ only) and profit by std::regex to solve those kind
    of problems with strings, starting from simple cases like the above. By
    looking at the code given by the OP and considering what "/" separators
    could be for, I don't think efficiency is the main concern there, nor
    the OP talked about efficiency explicitly.
     
    Luca Risolia, Mar 10, 2013
    #19
  20. Mike Copeland

    Nobody Guest

    On Sun, 10 Mar 2013 01:48:06 +0100, Luca Risolia wrote:

    >>>> if(str2.at(str2.length()-1) != '/') str2 +="/";
    >>>
    >>> str2 = std::regex_replace(str2, std::regex("[^/]$|^$"), "$&/");

    >>
    >> Is this an attempt to come up with the most convoluted and least
    >> efficient solution to the problem as you can?

    >
    > It's a great benefit to get familiar with regular expressions (which are
    > not specific to C++ only) and profit by std::regex to solve those kind
    > of problems with strings, starting from simple cases like the above. By
    > looking at the code given by the OP and considering what "/" separators
    > could be for, I don't think efficiency is the main concern there, nor
    > the OP talked about efficiency explicitly.


    But if you're going to learn to use regexps, you should at least learn to
    use them correctly. In particular, you shouldn't construct multiple
    temporary regexp objects from a given string literal, as constructing a
    regexp can be expensive.

    std::regex objects should normally be "static const". If you need to use
    the imbue() method, you should arrange for this to be done only once, as
    it will require the regexp to be recompiled.
     
    Nobody, Mar 10, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Earl Teigrob
    Replies:
    3
    Views:
    8,988
    Earl Teigrob
    Jan 6, 2004
  2. Peter Bencsik
    Replies:
    2
    Views:
    847
  3. Paul Rubin
    Replies:
    5
    Views:
    423
    Hendrik van Rooyen
    Aug 6, 2009
  4. Andrew Thompson
    Replies:
    8
    Views:
    154
    Premshree Pillai
    Jun 7, 2005
  5. Replies:
    2
    Views:
    57
    Mark H Harris
    May 13, 2014
Loading...

Share This Page