C++ equivalent of StringBuffer/StringBuilder?

前端 未结 10 878
说谎
说谎 2020-11-29 15:51

Is there a C++ Standard Template Library class that provides efficient string concatenation functionality, similar to C#\'s StringBuilder or Java\'s StringBuffer?

相关标签:
10条回答
  • 2020-11-29 16:30

    Since std::string in C++ is mutable you can use that. It has a += operator and an append function.

    If you need to append numerical data use the std::to_string functions.

    If you want even more flexibility in the form of being able to serialise any object to a string then use the std::stringstream class. But you'll need to implement your own streaming operator functions for it to work with your own custom classes.

    0 讨论(0)
  • 2020-11-29 16:30

    A convenient string builder for c++

    Like many people answered before, std::stringstream is the method of choice. It works good and has a lot of conversion and formatting options. IMO it has one pretty inconvenient flaw though: You can not use it as a one liner or as an expression. You always have to write:

    std::stringstream ss;
    ss << "my data " << 42;
    std::string myString( ss.str() );
    

    which is pretty annoying, especially when you want to initialize strings in the constructor.

    The reason is, that a) std::stringstream has no conversion operator to std::string and b) the operator << ()'s of the stringstream don't return a stringstream reference, but a std::ostream reference instead - which can not be further computed as a string stream.

    The solution is to override std::stringstream and to give it better matching operators:

    namespace NsStringBuilder {
    template<typename T> class basic_stringstream : public std::basic_stringstream<T>
    {
    public:
        basic_stringstream() {}
    
        operator const std::basic_string<T> () const                                { return std::basic_stringstream<T>::str();                     }
        basic_stringstream<T>& operator<<   (bool _val)                             { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (char _val)                             { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (signed char _val)                      { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (unsigned char _val)                    { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (short _val)                            { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (unsigned short _val)                   { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (int _val)                              { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (unsigned int _val)                     { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (long _val)                             { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (unsigned long _val)                    { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (long long _val)                        { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (unsigned long long _val)               { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (float _val)                            { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (double _val)                           { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (long double _val)                      { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (void* _val)                            { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (std::streambuf* _val)                  { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (std::ostream& (*_val)(std::ostream&))  { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (std::ios& (*_val)(std::ios&))          { std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (std::ios_base& (*_val)(std::ios_base&)){ std::basic_stringstream<T>::operator << (_val); return *this; }
        basic_stringstream<T>& operator<<   (const T* _val)                         { return static_cast<basic_stringstream<T>&>(std::operator << (*this,_val)); }
        basic_stringstream<T>& operator<<   (const std::basic_string<T>& _val)      { return static_cast<basic_stringstream<T>&>(std::operator << (*this,_val.c_str())); }
    };
    
    typedef basic_stringstream<char>        stringstream;
    typedef basic_stringstream<wchar_t>     wstringstream;
    }
    

    With this, you can write things like

    std::string myString( NsStringBuilder::stringstream() << "my data " << 42 )
    

    even in the constructor.

    I have to confess I didn't measure the performance, since I have not used it in an environment which makes heavy use of string building yet, but I assume it won't be much worse than std::stringstream, since everything is done via references (except the conversion to string, but thats a copy operation in std::stringstream as well)

    0 讨论(0)
  • 2020-11-29 16:37

    The std::string.append function isn't a good option because it doesn't accept many forms of data. A more useful alternative is to use std::stringstream; like so:

    #include <sstream>
    // ...
    
    std::stringstream ss;
    
    //put arbitrary formatted data into the stream
    ss << 4.5 << ", " << 4 << " whatever";
    
    //convert the stream buffer into a string
    std::string str = ss.str();
    
    0 讨论(0)
  • 2020-11-29 16:44

    You can use .append() for simply concatenating strings.

    std::string s = "string1";
    s.append("string2");
    

    I think you might even be able to do:

    std::string s = "string1";
    s += "string2";
    

    As for the formatting operations of C#'s StringBuilder, I believe snprintf (or sprintf if you want to risk writing buggy code ;-) ) into a character array and convert back to a string is about the only option.

    0 讨论(0)
提交回复
热议问题