Что такое обобщенный c и эффективный алгоритм обрезки для Qt & std :: string? - PullRequest
2 голосов
/ 24 апреля 2020

Чтобы удалить передние и задние пробелы, Qt предлагает QByteArray::trimmed(). Но это делает ненужную копию базовой строки каждый раз.

Есть ли какой-нибудь универсальный c и эффективный способ (предпочтительно с использованием шаблонов) для обрезки пробелов для QByteArray, QString, std:: string?

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Вы можете делать подобные вещи для каждого из них, но они не используют один и тот же интерфейс.

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());
}
0 голосов
/ 24 апреля 2020

Один простой способ c:

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 QString и QByteArray у нас может быть следующая оболочка:

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`
...