Алгоритм lexicographical_compare
является обобщенной версией strcmp
. Функция strcmp
работает только с символьными массивами, а lexicographical_compare
работает с интервалами значений любого типа. Кроме того, если strcmp
всегда сравнивает два символа и определяет отношение между ними (равенство, меньше, больше), то lexicographical_compare
может получать произвольный предикат, который определяет, удовлетворяют ли два значения пользовательскому критерию.
В предыдущем примере алгоритм lexicographical_compare
должен найти первую позицию, в которой s1
и s2
различаются по критерию ciCharLess
. Если для символов в этой позиции ciCharLess
возвращает true
, то же самое делает и lexicographical_compare
: если в первой позиции, где символы различаются, символ первой строки предшествует соответствующему символу второй строки, то первая строка предшествует второй. Алгоритм lexicographical_compare
, как и strcmp
, считает два интервала равных величин равными, поэтому для таких интервалов возвращается значение false
: первый интервал strcmp
, если первый интервал завершается до обнаружения различия, lexicographical_compare
возвращает true
— префикс предшествует любому интервалу, в который он входит.
Довольно о mismatch
и lexicographical_compare
. Хотя в этой книге большое значение уделяется переносимости программ, я просто обязан упомянуть о том, что функции сравнения строк без учета регистра символов присутствуют во многих нестандартных расширениях стандартной библиотеки C. Обычно эти функции называются stricmp
или strcmpi
и по аналогии с функциями, приведенными в данном совете, игнорируют проблемы интернационализации. Если вы готовы частично пожертвовать переносимостью программы, если строки заведомо не содержат внутренних нуль-символов, а проблемы интернационализации вас не волнуют, то простейший способ сравнения строк без учета регистра символов вообще не связан с STL. Обе строки преобразуются в указатели const char*
(см. совет 16), передаваемые при вызове stricmp
или strcmpi
:
int ciStringCompare(const string& si1, const string& s2) {
return stricmp(sl.c_str, s2.c_str); // В вашей системе вместо stricmp
} // может использоваться другое имя
Функции strcmp/strcmp
, оптимизированные для выполнения единственной задачи, обычно обрабатывают длинные строки mismatch
и lexicographical_compare
. Если быстродействие особенно важно в вашей ситуации, переход от стандартных алгоритмов STL к нестандартным функциям C вполне оправдан. Иногда самый эффективный путь использования STL заключается в том, чтобы вовремя понять, что другие способы работают лучше.
Совет 36. Правильно реализуйте copy_if
В STL имеется 11 алгоритмов, в именах которых присутствует слово copy
:
copy copy_backward
replace_copy reverse_copy
replace_copy_if unique_copy
remove_copy rotate_copy
remove_copy_if partial_sort_copy
uninitialized_copy
Но как ни странно, алгоритма copy_if
среди них нет. Таким образом, вы можете вызывать replace_copy_if
и remove_copy_if
, к вашим услугам copy_backward
и reverse_copy
, но если вдруг потребуется просто скопировать элементы интервала, удовлетворяющие определенному предикату, вам придется действовать самостоятельно.
Предположим, имеется функция для отбора «дефектных» объектов Widget
:
bool isDefective(const Widget& w);
Требуется скопировать все дефектные объекты Widget
из вектора в cerr
. Если бы алгоритм copy_if
существовал, это можно было бы сделать так:
vector
…
copy_if(widgets.begin, widgets.end, // He компилируется -
ostream_iterator
isDefective); // алгоритма copy_if
По иронии судьбы алгоритм copy_if
входил в исходную версию STL от Hewlett Packard, которая была заложена в основу библиотеки STL, ставшей частью стандартной библиотеки C++. В процессе сокращения HP STL до размеров, подходящих для стандартизации, алгоритм copy_if
остался за бортом.