Сравнение символьных строк
Дальше: Интернационализация сообщений Вверх: Интернационализация Назад: Форматирование чисел и дежежных
Сравнение символьных строк
Для лексикографического сравнения символьных строк с учетом установленного locale используются фунцкии strcoll и strxfrm. На работу этих фунцкий оказывает влияние значение категории LC_COLLATE. Для их использования необходимо подключать заголовочный файл string.h.Функция strcoll объявлена следующим образом:
int strcoll(const char *s1, const char *s2);и возвращает значения:
- 0, если символьные строки равны;
- > 0, если строка s1 ``больше'' (``позже'') s2 в соответствии с порядком букв в национальном алфавите, и
- < 0, если строка s1 ``меньше'' (``раньше'') s2.
Для описания функции strxfrm необходимо дать некоторые пояснения. Дело в том, что функция strcoll при сравнении строк переводит их в некоторое промежуточное представление в соответствии с текущим locale, и сравнение происходит не самих строк непосредственно, а этих промежуточных представлений. Функция strcoll деляет такое преобразование всегда и неявно. Функция strxfrm делает это преобразование явно, давая возможность пользователю получить промежуточное представление непосредственно. Эта возможность предусмотрена для тех ситуаций, когда сравнение небольшого количества одних и тех же строк производится многократно. Здесь рекомендуется получить промежуточные представления всех строк, а затем сравнивать уже эти промежуточные преставления непосредственно функцией strcmp -- результат будет тот же самый, что и при сравнении самих строк функцией strcoll.
Функция strxfrm объявлена следующим образом:
size_t strxfrm(char *dest, const char *src, size_t n);Выполняется преобразование строки str, первые n символов результата записываются в dest и возвращается количество байт, требуемых для сохранения результата (завершающий строку символ с кодом 0 не учитывается). Если возвращенное значение больше n, содержимое dest не определено.
Ниже приведен пример использования функций strcoll и strxfrm:
/* * strings.c * Использование функций strcoll и strxfrm. */ #include <stdio.h> #include <locale.h> #include <stdlib.h> #include <string.h> #ifdef _GNU_SOURCE extern char *program_invocation_short_name; #else const char *program_name; #define program_invocation_short_name program_name #endif /* _GNU_SOURCE */ typedef struct { char *string; /* Символьная строка */ char *string_internal_rep; /* Внутреннее представление, создаваемое функцией strxfrm */ int data; /* ... еще много чего */ } some_data; some_data some_array[] = { {"это", NULL, 1}, {"массив", NULL, 2}, {"строк", NULL, 3}, {"который", NULL, 4}, {"должен", NULL, 5}, {"быть", NULL, 6}, {"отсортирован", NULL, 7}, {"правильно", NULL, 8}}; void init_internal_reps (void) { some_data *dp; char strbuf[256]; for (dp = some_array; dp < some_array + sizeof(some_array)/sizeof(some_data); dp++) { strxfrm (strbuf, dp->string, strlen (dp->string)); if (!(dp->string_internal_rep = strdup (strbuf))) { fprintf (stderr, "%s: failed to duplicate string `%s'\n", program_invocation_short_name, dp->string_internal_rep); exit (1); } } } void print_result (char *about_message) { some_data *dp; printf ("%s\n", about_message); for (dp = some_array; dp < some_array + sizeof(some_array)/sizeof(some_data); dp++) printf ("{%s, %d}\n", dp->string, dp->data); } int cmp_by_string (const void *p, const void *q) { return strcoll (((some_data *)p)->string, ((some_data *)q)->string); } int cmp_by_internal_rep (const void *p, const void *q) { return strcmp (((some_data *)p)->string_internal_rep, ((some_data *)q)->string_internal_rep); } int cmp_to_restore_original_order (const void *p, const void *q) { return ((some_data *)p)->data - ((some_data *)q)->data; } int main (int argc, char *argv[]) { #ifndef _GNU_SOURCE program_name = argv[0]; #endif print_result ("Before sorting:"); init_internal_reps (); if (!setlocale (LC_COLLATE, "ru_SU")) { fprintf (stderr, "%s: failed to set locale\n", program_invocation_short_name); exit (1); } qsort (some_array, sizeof(some_array)/sizeof(some_data), sizeof(some_data), cmp_by_string); print_result ("After sorting by strings:"); qsort (some_array, sizeof(some_array)/sizeof(some_data), sizeof(some_data), cmp_to_restore_original_order); print_result ("After restoring original order:"); qsort (some_array, sizeof(some_array)/sizeof(some_data), sizeof(some_data), cmp_by_internal_rep); print_result ("After sorting by internal representation:"); return 0; }
Компилировать эту программу нужно примерно так же, как и предыдущий пример.
Dmitry A. Antipov
1999-05-26