Матрёшка: строки и UnicodeВ предыдущей статье (см. Матрёшка: символы и строки) было рассмотрено использование предоставляемых Матрёшкой строк, однако за рамками рассмотрения остались некоторые функции, тесно связанные со спецификацией Unicode как то преобразование регистра символов, сопоставление строк, нормализация и т.д. Далее в статье будет рассмотрено использование этих подпрограмм и даны некоторые рекомендации. СопоставлениеСопоставление строк есть особый вариант сравнения строк, позволяющий упорядочить сткроки в порядке, ожидаемом пользователем приложения. Алгоритм сопоставления достоточно сложен и ресурсоёмок, но эти затраты полностью окупаются удобством использования конечного приложения. Важно отметить, что алгоритм сопоставление принимает во внимание настройки языка конечного пользователя. Сопоставление выполняется в два этапа: сначала для каждой из строк формируется так называемый ключ сортировки, а затем выполняется сравнение ключей. Такой двухэтапный процесс позволяет значительно улучшить производительность при сравнении (например, сортировке) большого количества строк; поскольку ресурсоёмкий процесс формировнаия ключей сортировки выполняется только единожды а операция сравнения ключей сортировки использует обычное бинарное сравнение. Для предстваления ключа сортировки используется тип League.Strings.Sort_Key и получить ключ сортировки для строки с учётом текущих настроек языка пользователя можно с помощью подпрограммы Collation. Теперь настало время для примера: создадим два упорядоченных набора строк, для упорядочивания одного будет использоваться обычное бинарное стравнение, а для упорядочивания второго — сопоставление. with Ada.Containers.Ordered_Sets; with Ada.Wide_Wide_Text_IO; with League.Strings; procedure Collation is use type League.Strings.Sort_Key; package Binary_Order_Sets is new Ada.Containers.Ordered_Sets (League.Strings.Universal_String, League.Strings."<", League.Strings."="); function Less (Left : League.Strings.Universal_String; Right : League.Strings.Universal_String) return Boolean; function Equal (Left : League.Strings.Universal_String; Right : League.Strings.Universal_String) return Boolean; package Collation_Order_Sets is new Ada.Containers.Ordered_Sets (League.Strings.Universal_String, Less, Equal); ----------- -- Equal -- ----------- function Equal (Left : League.Strings.Universal_String; Right : League.Strings.Universal_String) return Boolean is begin return Left.Collation = Right.Collation; end Equal; ---------- -- Less -- ---------- function Less (Left : League.Strings.Universal_String; Right : League.Strings.Universal_String) return Boolean is begin return Left.Collation < Right.Collation; end Less; Binary : Binary_Order_Sets.Set; Collation : Collation_Order_Sets.Set; S1 : League.Strings.Universal_String := League.Strings.To_Universal_String ("ель"); S2 : League.Strings.Universal_String := League.Strings.To_Universal_String ("ёж"); S3 : League.Strings.Universal_String := League.Strings.To_Universal_String ("жук"); begin Binary.Insert (S1); Binary.Insert (S2); Binary.Insert (S3); Collation.Insert (S1); Collation.Insert (S2); Collation.Insert (S3); Ada.Wide_Wide_Text_IO.Put_Line ("Binary order:"); declare Position : Binary_Order_Sets.Cursor := Binary.First; begin while Binary_Order_Sets.Has_Element (Position) loop Ada.Wide_Wide_Text_IO.Put_Line (" " & Binary_Order_Sets.Element (Position).To_Wide_Wide_String); Binary_Order_Sets.Next (Position); end loop; end; Ada.Wide_Wide_Text_IO.Put_Line ("Collation order:"); declare Position : Collation_Order_Sets.Cursor := Collation.First; begin while Collation_Order_Sets.Has_Element (Position) loop Ada.Wide_Wide_Text_IO.Put_Line (" " & Collation_Order_Sets.Element (Position).To_Wide_Wide_String); Collation_Order_Sets.Next (Position); end loop; end; end Collation; Вывод примера будет следующим: Binary order: ель жук ёж Collation order: ёж ель жук Преобразование регистра символов При всей кажущейся простоте задача преобразования регистра символов (замена строчных букв заглавными или наоборот) для многих языков не столь тривиальна — прямая замена букв не даёт ожидаемый пользователем результат. Как следствие длина строки после преобразования регистра симолов может отличаться от длины исходной строки. К тому же помимо заглавных и строчных букв некоторые языки ещё оперируют особым регистром: буквы, используемые в заголовках. Матрёшка предоставляет реализацию всех необходимых подпрограмм преобразования регистра символов с учётом текущих настроек языка пользователя:
Строго говоря, имеется ещё одна подпрограмма преобразования регистра символов — To_Casefold — выполняющая «сворачивание» регистра символов. Её основное применение — сравнение строк без учёта регистра символов. И небольшой пример, показывающий использование и результат работы подпрограмм преобразования регистра: with Ada.Wide_Wide_Text_IO; with League.Strings; procedure Case_Conversion is S : League.Strings.Universal_String := League.Strings.To_Universal_String ("Ель"); begin Ada.Wide_Wide_Text_IO.Put_Line (S.To_Wide_Wide_String); Ada.Wide_Wide_Text_IO.Put_Line (S.To_Uppercase.To_Wide_Wide_String); Ada.Wide_Wide_Text_IO.Put_Line (S.To_Lowercase.To_Wide_Wide_String); Ada.Wide_Wide_Text_IO.Put_Line (S.To_Casefold.To_Wide_Wide_String); end Case_Conversion; НормализацияСпецификация Unicode вводит понятия нормализации текстовых данных и четыре формы нормализации. Матрёшка предоставляет четыре подпрограммы для выполнения нормализации в соответствующую нормальную форму — To_NFC, To_NFD, To_NFKC, To_NFKD. Применение нормализации регламентируется различными прикладными спецификациями, поэтому ограничимся только упоминанием наличия необходимых подпрограмм. Автор: Вадим Годунко |