C++ Equivalent of Stringbuffer/Stringbuilder

C++ equivalent of StringBuffer/StringBuilder?

The C++ way would be to use std::stringstream or just plain string concatenations. C++ strings are mutable so the performance considerations of concatenation are less of a concern.

with regards to formatting, you can do all the same formatting on a stream, but in a different way, similar to cout. or you can use a strongly typed functor which encapsulates this and provides a String.Format like interface e.g. boost::format

C++ best practice of concat strings

In case that somehow you think of StringBuilder in mananged realms.

You can use Alphabet (Google) Library, ABCLib, ABCL or just Abseil.

Abseil's Strings library look ahead and allocate all it need at once, then build string in it like you want. For concat job, you just need absl::StrCat() and absl::StrAppend().

I'm not any good at explaining things. Perhaps this godbolt link below may speak better than I do.

godbolt.org/g/V45pXJ

Learn more on YouTube : CppCon 2017: Titus Winters “Hands-On With Abseil” (ffw to 32min)

youtube.com/watch?v=xu7q8dGvuwk&t=32m

#include <string>
#include <iostream>
#include <absl/strings/str_cat.h>

int main()
{
std::string s1,s2,s3,s4,
s5,s6,s7,s8,
s9,s10,s11,s12;
std::getline(std::cin, s1);
std::getline(std::cin, s2);
std::getline(std::cin, s3);
std::getline(std::cin, s4);
std::getline(std::cin, s5);
std::getline(std::cin, s6);
std::getline(std::cin, s7);
std::getline(std::cin, s8);
std::getline(std::cin, s9);
std::getline(std::cin, s10);
std::getline(std::cin, s11);
std::getline(std::cin, s12);
std::string s = s1 + s2 + s3 + s4 + // a call to operator+ for each +
s5 + s6 + s7 + s8 +
s9 + s10 + s11 + s12;

// you shall see that
// a lot of destructors get called at this point
// because operator+ create temporaries

std::string abseil_s =
absl::StrCat(s1,s2,s3,s4, // load all handles into memory
s5,s6,s7,s8, // then make only one call!
s9,s10,s11,s12);

return s.size() + abseil_s.size();

// you shall see that
// only "real" s1 - s12 get destroyed
// at these point
// because there are no temporaries!

}


Update 2021

Today you can alternatively use fmt:format or std::format when the c++20 library implementation completed. (Current fmtlib now bumps support into c++14.)

The format will lookahead like in Abseil StrCat, so no wasted temporaries.

    string fmt_s = 
fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}",
s1,s2,s3,s4, // load all handles into memory
s5,s6,s7,s8, // then make only one call!
s9,s10,s11,s12);

[LIVE]

Python string class like StringBuilder in C#?

There is no one-to-one correlation. For a really good article please see Efficient String Concatenation in Python:

Building long strings in the Python
progamming language can sometimes
result in very slow running code. In
this article I investigate the
computational performance of various
string concatenation methods.

TLDR the fastest method is below. It's extremely compact, and also pretty understandable:

def method6():
return ''.join([`num` for num in xrange(loop_count)])

Does Qt5 have any class for similar to StringBuilder or StringBuffer?

QStringBuilder is not deprecated. From Qt docs:

In 4.6, an internal template class QStringBuilder has been added along with a few helper functions. This class is marked internal and does not appear in the documentation, because you aren't meant to instantiate it in your code. Its use will be automatic, as described below. The class is found in src/corelib/tools/qstringbuilder.cpp if you want to have a look at it.

Their code sample:

#include <QStringBuilder>

QString hello("hello");
QStringRef el(&hello, 2, 3);
QLatin1String world("world");
QString message = hello % el % world % QChar('!');

And you can use everything from C++ you need like std::stringstream.

Difference between StringBuilder and StringBuffer

StringBuffer is synchronized, StringBuilder is not.

What is the .NET equivalent of StringBuffer in Java?

It's System.Text.StringBuilder. Note that in modern Java you'd use java.lang.StringBuilder too. (It's like StringBuffer, but without the synchronization - I can't remember the last time I wanted the synchronization of StringBuffer. Note that the .NET StringBuilder isn't thread-safe either, but again, I can't remember the last time I found that to be a problem.)

equivalent of + in StringBuffer

Dont' use StringBuffer unless you have to. Java 5.0 and later uses StringBuilder by default

As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.

StringBuilder x = new StringBuilder("a");
StringBuilder y = new StringBuilder("b");
StringBuilder z = new StringBuilder().append(x).append(y);

String concatenation complexity in C++ and Java

C++ strings are mutable, and pretty much as dynamically sizable as a StringBuffer. Unlike its equivalent in Java, this code wouldn't create a new string each time; it just appends to the current one.

std::string joinWords(std::vector<std::string> const &words) {
std::string result;
for (auto &word : words) {
result += word;
}
return result;
}

This runs in linear time if you reserve the size you'll need beforehand. The question is whether looping over the vector to get sizes would be slower than letting the string auto-resize. That, i couldn't tell you. Time it. :)

If you don't want to use std::string itself for some reason (and you should consider it; it's a perfectly respectable class), C++ also has string streams.

#include <sstream>
...

std::string joinWords(std::vector<std::string> const &words) {
std::ostringstream oss;
for (auto &word : words) {
oss << word;
}
return oss.str();
}

It's probably not any more efficient than using std::string, but it's a bit more flexible in other cases -- you can stringify just about any primitive type with it, as well as any type that has specified an operator <<(ostream&, its_type&) override.

C# String.Substring equivalent for StringBuilder?

The StringBuilder class has a special version of the ToString method that takes two arguments, exactly as Substring(startIndex, length).

 StringBuilder sb = new StringBuilder("This is a Test");
string test = sb.ToString(10, 4);
Console.WriteLine(test); // result = Test

Fastest, leanest way to append characters to form a string in Swift

(This answer was written based on documentation and source code valid for Swift 2 and 3: possibly needs updates and amendments once Swift 4 arrives)

Since Swift is now open-source, we can actually have a look at the source code for Swift:s native String

  • swift/stdlib/public/core/String.swift

From the source above, we have following comment

/// Growth and Capacity
/// ===================
///
/// When a string's contiguous storage fills up, new storage must be
/// allocated and characters must be moved to the new storage.
/// `String` uses an exponential growth strategy that makes `append` a
/// constant time operation *when amortized over many invocations*.

Given the above, you shouldn't need to worry about the performance of appending characters in Swift (be it via append(_: Character), append(_: UniodeScalar) or appendContentsOf(_: String)), as reallocation of the contiguous storage for a certain String instance should not be very frequent w.r.t. number of single characters needed to be appended for this re-allocation to occur.

Also note that NSMutableString is not "purely native" Swift, but belong to the family of bridged Obj-C classes (accessible via Foundation).


A note to your comment

"I thought that String was immutable, but I noticed its append method returns Void."

String is just a (value) type, that may be used by mutable as well as immutable properties

var foo = "foo" // mutable 
let bar = "bar" // immutable
/* (both the above inferred to be of type 'String') */

The mutating void-return instance methods append(_: Character) and append(_: UniodeScalar) are accessible to mutable as well as immutable String instances, but naturally using them with the latter will yield a compile time error

let chars : [Character]  = ["b","a","r"]
foo.append(chars[0]) // "foob"
bar.append(chars[0]) // error: cannot use mutating member on immutable value ...


Related Topics



Leave a reply



Submit