Reputation: 11575
I have a QString
and I'd like to generate a new string with all characters separated. One way would be to iterate manually over the string and insert the separator after each character but the last one.
Is there a better method or at least a more direct one without having to implement the loop? For example, in order to use directly as function parameter. If possible, using Qt only.
const QString s("Hello world!");
const QString r(some_separating_function(s));
qDebug() << r;
The expected output would be
"H-e-l-l-o- -w-o-r-l-d-!"
EDIT: I'm self-answering it since I didn't find a better solution in SO and I find it useful. If anyone has a better solution I'll appreciate it.
Upvotes: 0
Views: 3924
Reputation: 11575
The best way I've found so far is to use the QString::split
method with an empty string as separator, which happens to create a QList
of individual characters (actually, a QList
with 1-character QString
s).
const QString s("Hello world!");
const QString r(s.split("", QString::SkipEmptyParts).join('-'));
Upvotes: 2
Reputation: 98505
Here's one way that doesn't allocate any temporaries:
// https://github.com/KubaO/stackoverflown/tree/master/questions/string-sep-42276882
#include <QtCore>
QString separate1(const QString & string, const QString & separator) {
QString result;
result.reserve(string.size() * (1 + separator.size()));
for (auto ch : string) {
result.append(ch);
result.append(separator);
}
result.chop(separator.size());
return result;
}
Alas, QString
's copy-on-write still has some overhead, so dealing with the data directly will be even faster:
QString separate(const QString & string, const QString & separator) {
QString result{string.size() + (string.size()-1) * separator.size(),
Qt::Uninitialized};
auto const end = result.data() + result.size();
int s{};
for (auto p = result.data(); p < end;) {
*p++ = string.at(s++);
if (Q_LIKELY(p < end))
for (auto const ch : separator)
*p++ = ch;
}
return result;
}
And to check it out:
int main() {
auto const separator = QStringLiteral("-");
auto const source = QStringLiteral("Hello world!");
auto const compare = QStringLiteral("H-e-l-l-o- -w-o-r-l-d-!");
Q_ASSERT(separate1(source, separator) == compare);
Q_ASSERT(separate(source, separator) == compare);
}
Upvotes: 1