Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QString trim non-whitespace characters from line begin or end

Tags:

c++

trim

qt

qstring

Some languages have ltrim(), rtrim() functions with arbitrary characters to trim, however seems QString in Qt does not have anything similar for now. How to implement such with current functionality? Regexp?

Note. Good if Qt team could add add ltrim(), rtrim() methods in QString() like some other languages have:

QString ltrim(QByteArray &chars); // trim left
QString rtrim(QByteArray &chars); // trim right

and overloaded

trimmed(QByteArray &chars)

to trim arbitrary characters, not only whitespaces. Should be very convenient.

like image 213
Aleksey Kontsevich Avatar asked Oct 23 '25 13:10

Aleksey Kontsevich


2 Answers

If you believe the feature is important then you can post a feature request on https://bugreports.qt.io/. If you look at qstring.cpp you can see the function is fairly simple and you can create your own custom function much faster.

You can trim whitespaces, \n, \r etc with QString::simplified();

qDebug() << QString(" lots\t of\nwhitespace\r\n ").simplified();

Output: lots of whitespace

or if you like to trim custom letters, you can use QString::remove with QRegExp:

qDebug() << QString("13Hello").remove(QRegExp("^([0-9]{2})")); // trim 2 numbers at begin
Output: Hello

qDebug() << QString("Hello13").remove(QRegExp("([0-9]{2})$")); // trim 2 numbers at the end
Output: Hello

qDebug() << QString(",./Hello").remove(QRegExp("^([,|.|/]+)")); // trim matched characters at the begin
Output: Hello

qDebug() << QString("Hello,./").remove(QRegExp("([,|.|/]+)$")); // trim matched characters at the end
Output: Hello
like image 105
user3606329 Avatar answered Oct 26 '25 03:10

user3606329


A QByteArray is not a way to store QChars: QString is. Given that, the implementation is not complicated. The switch-over point between using ws.contains and std::binary_search should be selected based on a benchmark.

The trimmedRef, trimmedLeftRef and trimmedRightRef are optimizations that don't copy the source string. They can be used when the trimmed version of the string doesn't outlive the source string - this avoids a copy.

#include <QString>
#include <algorithm>

namespace detail { struct IsSpace final {
  static QString sorted(QString s) {
    std::sort(s.begin(), s.end());
    return s;
  }
  QString const ws;
  QString::const_iterator begin = ws.cBegin(), end = ws.cEnd();
  bool (IsSpace::*test)(QChar) const = 
    ws.isEmpty()     ? &IsSpace::test1 :
    (ws.size() <= 8) ? &IsSpace::test2 :
                       &IsSpace::test3;
  explicit IsSpace(const QString &whitespace) : ws(sorted(whitespace)) {}
  bool test1(const QChar c) const { return c.isSpace(); }
  bool test2(const QChar c) const { return ws.contains(c); }
  bool test3(const QChar c) const { return std::binary_search(begin, end, c); }
  inline bool operator()(QChar c) const { return (*this.*test)(c); }
};  }

enum TrimmedOption { TrimmedLeft = 1, TrimmedRight = 2 };
Q_DECLARE_FLAGS(TrimmedOptions, TrimmedOption)
Q_DECLARE_OPERATORS_FOR_FLAGS(TrimedOptions)
QStringRef trimmedRef(const QString &src, const QString &whitespace,
  TrimmedOptions opt = TrimmedLeft | TrimmedRight) {
  detail::IsSpace const isSpace{whitespace};
  int l = 0;
  if (options & TrimmedLeft)
    while (l < src.length() && isSpace(src[l]))
      l++;
  int r = src.length();
  if (options & TrimmedRight)
    while (r > 0 && isSpace(src[r-1]))
      r--;
  return {&src, l, r-l};
}
QStringRef trimmedLeftRef(const QString &src, const QString &whitespace = {}) {
  return trimmedRef(src, whitespace, TrimmedLeft);
}
QStringRef trimmedRightRef(const QString &src, const QString &whitespace = {}) {
  return trimmed(src, whitespace, TrimmedRight);
}

QString trimmed(const QString &src, const QString &whitespace,
                TrimmedOptions opt = TrimmedLeft | TrimmedRight) {
  return trimmedRef(src, whitespace, opt);
}
QString trimmedLeft(const QString &src, const QString &whitespace = {}) {
  return trimmedRef(src, whitespace, TrimmedLeft);
}
QString trimmedRight(const QString &src, const QString &whitespace = {}) {
  return trimmedRef(src, whitespace, TrimmedRight);
}
like image 42
Kuba hasn't forgotten Monica Avatar answered Oct 26 '25 02:10

Kuba hasn't forgotten Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!