Шаг 383.
Библиотека STL.
Строки. Примеры использования итераторов со строками (продолжение)

    На этом шаге мы рассмотрим пример задания собственных критериев поиска и сортировки.

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

//---------------------------------------------------------------------------

#include <vcl.h>
#include <string>
#include <iostream>
#include <algorithm>

#include <conio.h>   //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;

std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

bool nocase_compare (char c1, char c2)
{
    return toupper(c1) == toupper(c2);
}


int main (int argc, char* argv[])
{
  string s1("This is a string");
  string s2("STRING");
  cout << ToRus("1-я строка:\n") << s1 << endl;
  cout << ToRus("2-я строка:\n") << s2 << endl;
    
  // Сравнение строк без учета регистра символов
  if (s1.size() == s2.size() &&        // Проверить совпадение размеров
      equal (s1.begin(),s1.end(),      // Первая строка
             s2.begin(),               // Вторая строка
             nocase_compare)) {        // Критерий сравнения
      cout << ToRus("Строки эквивалентны") << endl;
  }
  else {
      cout << ToRus("Строки не эквивалентны") << endl;
  }

  // Поиск без учета регистра символов
  string::iterator pos;
  pos = search (s1.begin(),s1.end(),   // Строка, в которой ведется поиск
                s2.begin(),s2.end(),   // Искомая подстрока
                nocase_compare);       // Критерий сравнения
  if (pos == s1.end()) {
      cout << ToRus("Строка s2 - подстрока строки s1") << endl;
  }
  else {
      cout << '"' << s2 << ToRus("\" - подстрока \"")
           << s1 << ToRus("\" (начиная с номера ") << pos - s1.begin() << ")"
           << endl;
  }


  getch();
  return 0;
}

//---------------------------------------------------------------------------
Текст этого примера можно взять здесь.

    Результат выполнения программы выглядит так:


Рис.1. Результат работы приложения

    Перед вызовом equal() нужно проследить за тем, чтобы количество элементов во втором интервале было по крайней мере не меньше, чем в первом. Этим объясняется необходимость сравнения размеров; без эгой проверки возможны непредсказуемые последствия.

    В последней команде вывода индекс символа вычисляется как разность двух итераторов:

pos - s1.begin()

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

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

  compose_f_gx_hy(equal_to<int>(), 
                  ptr_fun(toupper), 
                  ptr_fun(toupper))

    За дополнительной информацией обращайтесь к шагам 247 и 252.

    При хранении строк в множествах или отображениях может потребоваться специальный критерий сортировки строк без учета регистра символов. На 184 шаге приведен пример определения такого критерия.

    На следующем шаге мы продолжим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг