Сравнение строк

Последнее обновление: 02.03.2023

К строкам в языке С++ можно применять операции сравнения.

> >= < <= == != <=>

Эти операции сравнивают два объекта string, либо объект string со строковым литералом. Во всех операцияъ операнды сравниваются посимвольно до тех пор, пока не будет найдена пара соответствующих символов, которые содержат разные символы, или пока не будет достигнут конец одного или обоих операндов. Когда пара символов различается, с помощью сравнение числовых кодов символов определяется, какая строка условно "меньше" или "больше". Если разные пары символов не найдены, но строки имеют разную длину, более короткая строка «меньше» более длинной строки. Две строки равны, если они содержат одинаковое количество символы и все соответствующие коды символов равны. Подобный способ сравнения еще называется лексикографическим сравнением или сравнением в лексикографическом порядке. При этом стоит отметить, что поскольку сравниваются числовые коды символов, результат сравнения также зависит от регистра символов.

Например, оператор == возвращает true, если все символы обеих строк равны.

std::string s1 {"hello"};
 
bool result {s1 == "Hello"}; // false - строки различаются по регистру
result = s1 == "hello";     // true

Поскольку строки "hello" и "Hello" отличаются по регистру первой буквы, соответственно отличается и числовой код символа, поэтому эти строки не равны.

Другой пример - операция > (больше):

std::string s1 {"helm"}; std::string s2 {"hello"}; bool result {s1 > s2}; // true

В данном случае условие s1 > s2 верно, то есть s1 больше чем s2, так как при равенстве первых трех символов ("hel") третий символ первой строки ("m") стоит в алфавите после четвертого символа второй строки ("l"), то есть "m" больше чем "l" (несмотря на то, что по количеству символов "hello" больше чем "helm").

Возьмем небольшую программу. Например, у нас есть массив имен, и нам надо отсортировать их в алфавитном порядке:

#include <iostream>
#include <string>

int main()
{
    std::string people[] {"Tom", "Alice", "Sam", "Bob", "Kate"}; 
     // сортируем по возрастанию
    bool sorted {};
    do
    {
        sorted = true;      // остается true, если строки отсортированы
        std::string temp;   // переменная для обмена значениями
        for (unsigned i {1}; i < std::size(people); i++)
        {
            // если предыдущая строка больше последующей
            if (people[i-1] > people[i])
            { 
                // обмениваем значения
                temp = people[i];
                people[i] = people[i-1];
                people[i-1] = temp;
                sorted = false;
            }
        }
    } while (!sorted);
	// вывод строк на консоль
    for (const auto person: people) 
    {
        std::cout << person << std::endl;
    }
}

Здесь для сортировки массива строк применяется не самая быстрая, но наглядная сортировка пузырьком, которая сравнивает предыдущую строку с последующей. Если предыдущая "больше" последующей, то через промежуточную переменную temp обмениваем значения. Чтобы оптимизировать сортировку, добавлена переменная sorted. Каждый раз, когда производится обмен значениями, эта переменная сбрасывается в false. А это значит, что нам надо заново запустить внешний цикл do-while.

Консольный вывод:

Alice
Bob
Kate
Sam
Tom

Функция compare()

Для сравнения строк у строки также можно вызвать функцию compare(). В нее передается другая строка, с которой сравнивается текущая. Функция compare возвращает 0, если две строки равны. Если текущая строка больше, то возвращается число больше 0. Если текущая строка меньше, то возвращается число менише 0. Например:

std::string tom {"Tom"};
std::string person{"Tom"};
int result = tom.compare(person);
std::cout << result << std::endl;   // 0 - строки равны

Здесь две строки равны, поэтому возвращается число 0.

Другой пример:

std::string tom {"Tom"};
std::string bob{"Bob"};
std::string sam {"Sam"};
    
int result = sam.compare(bob);      // 1 - первая строка (sam) больше второй (bob)
std::cout << result << std::endl;   // 1

result = sam.compare(tom);      // -1 - первая строка (sam) меньше второй (tom)
std::cout << result << std::endl;   // -1

Здесь строка "Sam" больше строки "Bob", поэтому результатом первого сравнения будет число 1. А во втором сравнении первая строка "Sam" будет меньше второй строки "Tom", соответственно функция возвратить -1.

Функция compare() имеет ряд версий. Отметим одну из них, которая принимает три параметра:

int compare(size_t _Off, size_t _Nx, const std::string &_Right) const

Первый параметр представляет индекс первого символа в текущей строке, начиная с которого начинается подстрока. Второй параметр - количество символов подстроки. Третий параметр - строка, которая сравнивается подстрока. То есть сравниваем строку из третьего параметра с подстрокой, которая начинается с индекса в первом параметре и имеет количество символов, указанных во втором параметре.

Где мы это можем применить? Например, нам надо узнать индекс, с которого встречается одна строка в другой:

#include <iostream>
#include <string>

int main()
{
    std::string text {"Hello world!"};
    std::string word {"world"};
    for (unsigned i{}; i < text.length() - word.length() + 1; i++)
    {
        if (text.compare(i, word.length(), word) == 0)
        {
            std::cout << "text contains " << word << " at index " << i << std::endl;
        }
    }
}

В данном случае мы пытаемся найти индекс строки word ("world") в строке text ("Hello world!"). Для этого в цикле проходим по символам из строки text, пока не дойдем до символа с индексом text.length() - word.length() + 1 (так как сравниваем word.length() символов, поэтому вычитаем word.length(). И так как строки могут быть равны, добавляем 1)

В цикле выполняем сравнение

if (text.compare(i, word.length(), word) == 0)

то есть в строке text сравниваем подстроку, которая начинается с индекса i и имеет word.length() символов с строкой word. Если для какого то числа i мы смогли найти подобное равенство, то выводим число i на консоль. И в данном случае консоль отобразит следующее

text contains world at index 6

Еще одна форма функции compare() позволяет сравнивать две подстроки:

#include <iostream>
#include <string>

int main()
{
    std::string text {"Hello world!"};
    std::string word {"world"};
    unsigned size {2}; // число сравниваемых символов из второй строки
    for (unsigned i{}; i < text.length() - size + 1; i++)
    {
        if (text.compare(i, size, word, 1, size) == 0)
        {
            std::cout << "text contains substring at index " << i << std::endl;
        }
    }
}

Здесь в принципе тот же алгоритм, что и с предыдущем примере. Только теперь сравниваем из строки word подстроку размером size, которая начинаяется с индекса 1 (то есть подстрока "or"), с подстрокой из строки text. И в данном случае консольный вывод будет следующим

text contains substring at index 7
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850