Как назначить '-' равно '' для сравнения классов строк, это возможно? - PullRequest
0 голосов
/ 04 января 2012

Я сравниваю две строки, str1 и str2, используя функцию string.compare в #string.Есть ли способ заставить класс думать, что '-' эквивалентно ' '.Глядя на функции-члены char_traits, я подумал, что .assign позволит мне это сделать, но он действует так, как будто я говорю, str1='-'; или str1=' ';.Я бы предпочел не переписывать свой собственный класс обработки строк.

Ответы [ 6 ]

4 голосов
/ 04 января 2012

Как насчет копирования и замены всех вхождений "-" на "" перед сравнением двух строк?

3 голосов
/ 04 января 2012

В библиотеке нет ничего для такого конкретного случая использования, но это легко сделать самостоятельно:

  1. Сделайте копию обеих строк. В каждом замените все '-' на ' '. Затем выполните сравнение этих строк;

  2. Либо создайте собственную собственную функцию, которая выполняет итерацию по каждому символу и выполняет лексикографическое сравнение с описанной вами дополнительной семантикой. Преимущество этого состоит в том, что не требуется копировать строки, но будет больше кода и, возможно, больше подвержено ошибкам.

1 голос
/ 04 января 2012

Стандартная библиотека C ++ предоставляет мощные алгоритмы для этого.Кажется, вы хотите использовать std::mismatch() вместе с пользовательским предикатом, считая '-' и '' идентичными.Это будет выглядеть примерно так:

bool pred(char c0, char c1) {
    return c0 == c1
          || (c0 == '-' && c1 == ' ')
          || (c0 == ' ' && c1 == '-');
}

std::string const& s(s0.size() < s1.size()? s0: s1);
std::string const& l(s0.size() < s1.size()? s1: s0);
auto p = std::mismatch(s.begin(), s.end(), l.begin(), pred);

После этого p - это пара итераторов, указывающая на первый символ, который отличается (или конечный итератор).Чтобы определить, какую строку сортировать до или после того, как вы просто оцените результат.

Интерфейс немного раздражает тем, что более короткая последовательность должна сначала: должны быть ограничения для обоих концов.

1 голос
/ 04 января 2012

Есть несколько возможностей, в зависимости от того, хотите ли вы это поведение:

  • раз
  • закодировано в классе

Если вы хотите вести себя один раз: просто используйте свой собственный (пользовательский) алгоритм:

bool isSpace(char i) { return i == '-' or i == ' '; }

int compare(std::string const& left, std::string const& right) {
  typedef std::string::const_iterator ConstIterator;
  typedef std::pair<ConstIterator, ConstIterator> Result;

  size_t const size = std::min(left.size(), right.size());

  Result const r = std::mismatch(left.begin(),
                                 left.begin() + size,
                                 right.begin(),
                                 [](char a, char b) {
                                   return a == b or (isSpace(a) and isSpace(b));
                                 });

  if (r.first == left.begin() + size) { // equal up til the end, shorter wins
    return left.size() < right.size() ? -1 :
          (left.size() == right.size() ? 0 : 1);
  }

  // not equal until the end
  return *r.first < *r.second ? -1 : 1;
}

Если это поведение необходимо кодировать внутри самого класса, вам нужно использовать basic_string и предоставить пользовательский класс черты.

Класс черт предоставляет функцию static int compare ( const char_type* s1, const char_type* s2, size_t n);, которая используется std::string::compare под капотом.

Так, например:

struct MyTraits: char_traits<char> // too lazy to reimplement everything
{
  static int compare(const char_type* s1, const char_type* s2, size_t n);
  // definition can be trivially derived from the above version
};

typedef std::basic_string<char, MyTraits> MyString;

Конечно, MyString тогда совершенно несовместим с другими std::string.


Честно говоря, если можете, просто "нормализуйте" свою строку и решите, будете ли вы использовать '-' или ''. Это облегчит вашу жизнь.

1 голос
/ 04 января 2012

Простой способ состоит в том, чтобы сложить строки, т.е. просто заменить все "-" на "" перед их сравнением.

0 голосов
/ 04 января 2012

(сообщество-вики, не стесняйтесь вносить свой вклад.)

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

#include<iostream>
using namespace std;

struct newchar {
        char c;
        bool operator <(const newchar &other) const {
                return this->c < other.c;
        }
        newchar(char c_): c(c_) {
                fixme();
        }
        newchar(): c('\0') {}
        newchar & operator = (const newchar &in) {
                this->c = in.c;
                fixme();
                return *this;
        }
        void fixme() {
                if(c=='-')
                        c = ' ';
        }
};

struct newstring : basic_string<newchar> {
        string toCharString() const {
                std :: string s;
                for(const_iterator i = this->begin(); i != this->end(); i++) {
                        char c = i->c;
                        s += c;
                }
                return s;
        }
};
ostream& operator<< (ostream & os, const newstring &ns) {
        os << ns.toCharString();
        return os;
}

int main() {
        newstring s;
        s.compare(s);
        s += 'k';
        cout << '<' << string() << '>' << endl;
        cout << '<' << s << '>' << endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...