Как перегрузить оператор == для строкового класса в С++?

Я новый c++ программист и только недавно узнал о перегрузке операторов. Во время работы над независимым проектом я столкнулся с проблемой: я хотел сравнить строки ввода пользователя с другими строками, чтобы позволить пользователю перемещаться по простому меню. Единственное, я не знаю, как сравнивать две строки, игнорируя регистр. Если есть гораздо более простой способ сделать это, чем перегружать оператор ==, пожалуйста, дайте мне знать, а также дайте мне знать, как перегрузить оператор == для строк, потому что мне это очень интересно.

Какое отличное сообщество. Большое спасибо, ребята, вы очень быстро ответили на мой вопрос, не заставив меня чувствовать себя глупо!


person Anton Yershov    schedule 19.03.2013    source источник
comment
Пункт 35 действующего STL.   -  person Alex Chamberlain    schedule 19.03.2013
comment
Я уже читал ту ветку. Это не ответило на то, что я спрашивал.   -  person Anton Yershov    schedule 19.03.2013
comment
Соответствующий пример здесь.   -  person juanchopanza    schedule 19.03.2013
comment
Сладкое спасибо, но я думаю, что мой вопрос был дан ответ. Ожидание 3 минуты, чтобы выбрать принятый ответ. :)   -  person Anton Yershov    schedule 19.03.2013


Ответы (2)


Ну, я должен сделать несколько замечаний здесь.

  • Если под строкой вы имеете в виду массивы/указатели char, то вы не можете перегружать оператор ==, так как перегрузка оператора разрешена только для пользовательских типов

  • Если под строками имеется в виду std::string, то и оператор == перегружать нельзя, так как он уже перегружен :)

  • Для сравнения без учета регистра лучше всего использовать именованную функцию, например case_insensitive_equal. У Boost есть один - boost::iequals(str1, str2)

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

Что касается как написать функцию, сравнивающую строки без учета регистра, я бы сделал следующее:

bool case_insensitive_equal(const std::string& s1, const std::string& s2)
{
    if(s1.length() != s2. length())
       return false;
    for(int i = 0; i < s1.length(); ++i)
        if(std::toupper(s1[i]) != std::toupper(s2[i])) //tolower would do as well
            return false;
    return true;
}

Вместо циклов можно использовать std::transform и std::equal, но я думаю, что это более эффективно.

person Armen Tsirunyan    schedule 19.03.2013
comment
Большое спасибо! Это действительно помогает. Но зачем вам нужно ставить & перед s1 и s2? В этом случае вы на самом деле не меняете значения строк. - person Anton Yershov; 19.03.2013
comment
@Anton: Да, действительно, нет, поэтому там const. Я передаю аргументы по ссылке, чтобы избежать ненужного копирования - person Armen Tsirunyan; 19.03.2013
comment
Хорошо, так это просто для сохранения памяти? - person Anton Yershov; 19.03.2013
comment
@AntonYershov: Избегание копирования не экономит память. Это экономит время. Если бы у вас было две строки по 1 МБ, их копирование в функцию заняло бы довольно много времени, тогда как в этом нет абсолютно никакой необходимости. - person Armen Tsirunyan; 19.03.2013
comment
Я думаю, вы можете использовать std::equal без std::transform. Существует перегрузка, которая принимает двоичный предикат. - person juanchopanza; 19.03.2013
comment
@juanchopanza: Да, ты прав, я забыл :) - person Armen Tsirunyan; 19.03.2013
comment
Ваш код будет работать только для локалей на основе ascii... - person PlasmaHH; 19.03.2013

Вы не перегружаете operator== для std::string, потому что вам пришлось бы поместить оператор в пространство имен std. Это (а) не разрешено и (б) уже сделано реализацией стандартной библиотеки.

Также не рекомендуется перегружать любое operator==, чтобы оно означало что-то иное, кроме истинного равенства. т.е. если a == b, то a и b должны вести себя одинаково.

Что вам следует сделать, так это написать отдельную функцию со значимым именем, например.

bool areEqualIgnoringCase(const std::string&, const std::string&);
person CB Bailey    schedule 19.03.2013
comment
Не уверен, что вам нужно изменить пространство имен std... - person Alex Chamberlain; 19.03.2013
comment
@AlexChamberlain: Как бы еще вы написали operator== вместо std::string? - person CB Bailey; 19.03.2013
comment
namespace ADC { bool operator==(std::string const&, std::string const&); } Не уверен, что это сработает для std::string, у которого уже есть operator==. - person Alex Chamberlain; 19.03.2013
comment
@AlexChamberlain: Конечно, если вы хотите позвонить своему оператору так: ADC::operator == (s1, s2); :D - person Armen Tsirunyan; 19.03.2013