Сравнение символьных строк
Дальше: Интернационализация сообщений Вверх: Интернационализация Назад: Форматирование чисел и дежежных
Сравнение символьных строк
Для лексикографического сравнения символьных строк с учетом установленного 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
