代码之家  ›  专栏  ›  技术社区  ›  Aleksey Kontsevich

QString从行开始或结束修剪非空白字符

  •  2
  • Aleksey Kontsevich  · 技术社区  · 8 年前

    有些语言有ltrim()、rtrim()函数,可以修剪任意字符,但Qt中的QString目前似乎没有任何类似的功能。如何利用当前的功能实现这样的功能?Regexp?

    笔记 如果Qt团队可以像其他一些语言一样,在QString()中添加add ltrim()、rtrim()方法,这很好:

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

    和过载

    trimmed(QByteArray &chars)
    

    要修剪任意字符,而不仅仅是空格。应该很方便。

    2 回复  |  直到 8 年前
        1
  •  2
  •   Aleksey Kontsevich    8 年前

    如果您认为该功能很重要,则可以在上发布功能请求 https://bugreports.qt.io/ .如果你看 qstring.cpp 您可以看到该函数非常简单,您可以更快地创建自己的自定义函数。

    您可以修剪空白, \n ,则, \r etc与 QString::simplified() ;

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

    或者,如果您想修剪自定义字母,可以使用 QString::remove 具有 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
    
        2
  •  1
  •   Kuba hasn't forgotten Monica    8 年前

    A. QByteArray 不是存储的方式 QChar s: QString 是有鉴于此,实现并不复杂。使用之间的切换点 ws.contains std::binary_search 应基于基准进行选择。

    这个 trimmedRef ,则, trimmedLeftRef trimmedRightRef 是不复制源字符串的优化。当字符串的修剪版本不超过源字符串时,可以使用它们-这样可以避免复制。

    #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);
    }