【问题标题】:What's the generic & efficient trimming algorithm for Qt & std::string?Qt & std::string 的通用高效修剪算法是什么?
【发布时间】:2020-08-07 20:27:04
【问题描述】:

要删除前后空格,Qt 提供了QByteArray::trimmed()。但它每次都不必要地复制底层字符串。

是否有任何通用且有效的方法(最好使用模板)来修剪QByteArray, QString, std:: string 的空白?

【问题讨论】:

  • 你用 c++14 标记了你的问题,所以我猜std::string_view (C++17) 是不可能的?
  • @Botje,是的,我们的主要兼容性是与 C++14 兼容,而 C++17 尚未得到支持。如果它也支持 Qt 的字符串类型,你能否用 C++17 回答你的观点。
  • 如果您不介意将未修剪的版本保留为底层 QString,QStringView::trimmed 可能是一个选项(对于 QString)。
  • @FrankOsterfeld,这就是问题的主题。如前所述,trimmed() 效率低下,而且 Qt 总是创建一个新字符串是愚蠢的。他们应该给出一个非常量的方法,例如trim(),它适用于现有的字符串。
  • 我说的是 QStringView::trimmed,而不是 QString::trimmed

标签: c++ string qt c++14 removing-whitespace


【解决方案1】:

您可以为它们中的每一个做类似的事情,但它们不使用相同的界面。

void trim(std::string & str)
{
    auto first = std::find_if_not(str.begin(), str.end(), [](unsigned char c){ return std::isspace(c); });
    auto last = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char c){ return std::isspace(c); }).base();

    if (first != str.begin())
    {
        std::move(first, last, str.begin());
    }

    str.erase(last, str.end());
}

void trim(QString & str)
{
    auto first = std::find_if_not(str.begin(), str.end(), [](unsigned char c){ return std::isspace(c); });
    str.remove(0, first - str.begin());

    auto last = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char c){ return std::isspace(c); }).base();
    str.resize(last - str.begin());
}

【讨论】:

    【解决方案2】:

    一种简单的方法:

    template<typename T>
    T& Trim (T& value)
    {
      auto pos = value.size();
      while(pos != 0 and value[--pos] == ' ');
      if(++pos < value.size())
        value.erase(pos);
    
      if(value.size() > 0)
      {
        pos = -1;
        while(value[++pos] == ' ');
        if(pos > 0)
          value.erase(0, pos);
      }
      return value;
    }
    

    以上将支持所有具有以下方法的类型,如std::string

    • size()
    • operator[] const
    • erase(pos, n)

    不幸的是,Qt 只是缺少erase()(名称是remove())。为了支持 Qt 类型 QStringQByteArray,我们可以有以下包装器:

    template<class String>
    struct QtWrap
    {
      String& m_Value;
    
      auto size () const { return m_Value.size(); }
      auto erase (int pos) { return m_Value.truncate(pos); }
      auto erase (int pos, int length) { return m_Value.remove(pos, length); }
      auto& operator[] (const int pos) const { return m_Value.data()[pos]; }
    };
    

    用法:

    QByteArray s;
    QtWrap<QByteArray> qs{s};
    Trim(qs);  // Tested OK in QtCreator: Modifies the underlying `s`
    

    【讨论】:

      猜你喜欢
      • 2010-09-18
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      相关资源
      最近更新 更多