Как может я делать карту:: найти операцию нечувствительной к регистру?

Я считаю, что идеальным инструментом для решения вашей проблемы является Diver: динамические интерактивные представления для обратного инжиниринга. Он предоставляет как статические, так и динамические диаграммы последовательности и ищет решения всех ваших требований по вашему вопросу.

Это плагин для Eclipse, позволяющий вам:

  • Легко отслеживать ваши Java-программы
  • Визуализировать функциональность вашей программы во время выполнения
  • Фильтровать ваши трассировки чтобы сделать их более компактными
  • Фильтруйте вашу IDE на основе того, что происходит во время выполнения
  • Посмотрите, какой код запускался в ваших редакторах исходного кода

Это на Github и есть также веб-сайт проекта

Полное раскрытие: я являюсь ведущим проекта Diver

47
задан honk 15 March 2019 в 14:15
поделиться

8 ответов

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

  /************************************************************************/
  /* Comparator for case-insensitive comparison in STL assos. containers  */
  /************************************************************************/
  struct ci_less : std::binary_function<std::string, std::string, bool>
  {
    // case-independent (ci) compare_less binary function
    struct nocase_compare : public std::binary_function<unsigned char,unsigned char,bool> 
    {
      bool operator() (const unsigned char& c1, const unsigned char& c2) const {
          return tolower (c1) < tolower (c2); 
      }
    };
    bool operator() (const std::string & s1, const std::string & s2) const {
      return std::lexicographical_compare 
        (s1.begin (), s1.end (),   // source range
        s2.begin (), s2.end (),   // dest range
        nocase_compare ());  // comparison
    }
  };

Используйте его как std :: map , ci_less> myMap;

ПРИМЕЧАНИЕ : std :: lexicographic_compare содержит несколько мельчайших деталей. Сравнение строк не всегда прямолинейно, если учитывать языковые стандарты. Если интересно, см. этот поток на clc ++.

ОБНОВЛЕНИЕ : в C ++ 11 std :: binary_function устарел и не требуется, поскольку типы выводятся автоматически.

  struct ci_less
  {
    // case-independent (ci) compare_less binary function
    struct nocase_compare
    {
      bool operator() (const unsigned char& c1, const unsigned char& c2) const {
          return tolower (c1) < tolower (c2); 
      }
    };
    bool operator() (const std::string & s1, const std::string & s2) const {
      return std::lexicographical_compare 
        (s1.begin (), s1.end (),   // source range
        s2.begin (), s2.end (),   // dest range
        nocase_compare ());  // comparison
    }
  };
66
ответ дан 26 November 2019 в 19:27
поделиться

Вы можете создать экземпляр std :: map с тремя параметрами: типом ключей, типом значений и функцией сравнения - строгое слабое упорядочение (по сути, функция или функтор, ведущий себя как operator < с точки зрения транзитивности и антирефлексивности) по вашему вкусу. Просто определите третий параметр, чтобы сделать «меньше чем» без учета регистра (например, с помощью < в строках с нижним регистром, которые он сравнивает), и вы получите желаемую «карту без учета регистра»!

6
ответ дан 26 November 2019 в 19:27
поделиться

Нет, вы не можете сделать это с помощью find , так как в этом случае будет несколько совпадений. Например, при вставке вы можете сделать что-то вроде map ["A"] = 1 и map ["a"] = 2 , а теперь, если вам нужен регистр без учета ] map.find ("a") какое ожидаемое возвращаемое значение? Самый простой способ решить эту проблему - вставить строку в карту только в одном регистре (в верхнем или нижнем регистре), а затем использовать тот же регистр при поиске.

3
ответ дан 26 November 2019 в 19:27
поделиться

Для элемента сравнения шаблона карты по умолчанию используется класс двоичного сравнения «меньше». Посмотрите на реализацию:

http://www.cplusplus.com/reference/std/functional/less/

Вероятно, вы можете создать свой собственный класс, производный от binary_function (родительский класс для less) и выполнить такое же сравнение без учета регистра.

1
ответ дан 26 November 2019 в 19:27
поделиться

В случае, если вы не хотите касаться типа карты (чтобы сохранить его первоначальную простоту и эффективность), но не возражаете использовать более медленную функцию поиска без учета регистра (O ( N)):

string to_lower(string s) {
    transform(s.begin(), s.end(), s.begin(), (int(*)(int)) tolower );
    return s;
}

typedef map<string, int> map_type;

struct key_lcase_equal {
    string lcs;
    key_lcase_equal(const string& s) : lcs(to_lower(s)) {}
    bool operator()(const map_type::value_type& p) const {
        return to_lower(p.first) == lcs;
    }
};

map_type::iterator find_ignore_case(map_type& m, const string& s) {
    return find_if(m.begin(), m.end(), key_lcase_equal(s));
}

PS: Возможно, это была идея Роджера Пейта, но не уверен, так как некоторые детали были немного неточными (std :: search?, Прямой компаратор строк?)

4
ответ дан 26 November 2019 в 19:27
поделиться

Реализуйте функцию std :: less и сравните, изменив обе на один и тот же регистр.

0
ответ дан 26 November 2019 в 19:27
поделиться

Я использую следующее:

bool str_iless(std::string const & a, 
               std::string const & b)
{
    return boost::algorithm::lexicographical_compare(a, b,  
                                                     boost::is_iless());
}
std::map<std::string, std::string, 
         boost::function<bool(std::string const &, 
                              std::string const &)> 
         > case_insensitive_map(&str_iless);
5
ответ дан 26 November 2019 в 19:27
поделиться

Вот еще несколько альтернатив, в том числе одна, которая работает значительно быстрее.

#include    <map>
#include    <string>
#include    <cstring>
#include    <iostream>
#include    <boost/algorithm/string.hpp>

using std::string;
using std::map;
using std::cout;
using std::endl;

using namespace boost::algorithm;

// recommended in Meyers, Effective STL when internationalization and embedded
// NULLs aren't an issue.  Much faster than the STL or Boost lex versions.
struct ciLessLibC : public std::binary_function<string, string, bool> {
    bool operator()(const string &lhs, const string &rhs) const {
        return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ;
    }
};

// Modification of Manuel's answer
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
    bool operator() (const std::string & s1, const std::string & s2) const {
        return lexicographical_compare(s1, s2, is_iless());
    }
};

typedef map< string, int, ciLessLibC> mapLibc_t;
typedef map< string, int, ciLessBoost> mapBoost_t;

int main(void) {
    mapBoost_t cisMap; // change to test other comparitor 

    cisMap["foo"] = 1;
    cisMap["FOO"] = 2;

    cisMap["bar"] = 3;
    cisMap["BAR"] = 4;

    cisMap["baz"] = 5;
    cisMap["BAZ"] = 6;

    cout << "foo == " << cisMap["foo"] << endl;
    cout << "bar == " << cisMap["bar"] << endl;
    cout << "baz == " << cisMap["baz"] << endl;

    return 0;
}
23
ответ дан 26 November 2019 в 19:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: