Estoy buscando un método para comparar y ordenar cadenas UTF-8 en C++ de una manera insensible a mayúsculas y minúsculas para usarlo en un custom collation function in SQLite.Intercalación de cadenas UTF-8 insensible a mayúsculas/minúsculas para SQLite (C/C++)
- El método debería idealmente ser independiente de la Localidad. Sin embargo, no voy a contener la respiración, hasta donde yo sé, la intercalación es muy dependiente del idioma, por lo que todo lo que funciona en idiomas distintos del inglés servirá, incluso si esto significa cambiar de configuración.
- opciones incluyen el uso de C estándar o biblioteca de C++ o una pequeña (adecuado para el sistema integrado) y (adecuado para un sistema propietario) biblioteca-GPL no de terceros.
Lo que tengo hasta ahora:
strcoll
con lugares C ystd::collate
/std::collate_byname
entre mayúsculas y minúsculas. (¿Hay versiones mayúsculas y minúsculas de estos?)He intentado utilizar un strcasecmp POSIX, pero parece ser not defined para otras localizaciones distintas a
"POSIX"
En la localización POSIX, strcasecmp() y strncasecmp() hace conversiones de mayor a menor, luego una comparación de bytes. Los resultados no están especificados en otras configuraciones regionales.
Y, de hecho, el resultado de
strcasecmp
no cambia de un entorno nacional en Linux con glibc.#include <clocale> #include <cstdio> #include <cassert> #include <cstring> const static char *s1 = "Äaa"; const static char *s2 = "äaa"; int main() { printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); assert(setlocale(LC_ALL, "en_AU.UTF-8")); printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); assert(setlocale(LC_ALL, "fi_FI.UTF-8")); printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); }
Esto se imprime:
strcasecmp('Äaa', 'äaa') == -32 strcoll('Äaa', 'äaa') == -32 strcasecmp('Äaa', 'äaa') == -32 strcoll('Äaa', 'äaa') == 7 strcasecmp('Äaa', 'äaa') == -32 strcoll('Äaa', 'äaa') == 7
PS
Y sí, soy consciente de ICU, pero no podemos usarlo en la plataforma embebida debido a su enormous size .
Sobre su ejemplo con el carácter alemán "ß" (y todos esos casos abundantes): estos deben haber sido "resueltos" o tratados de otra manera miles de veces antes, UTF-8 o no. MS Word siempre ha tenido una función de "alternar mayúsculas y minúsculas". ¿Cómo funcionaba con ese personaje en las versiones anteriores a Unicode? ¿Cómo funciona WordPerfect? Estoy teniendo el mismo problema que el OP, excepto que trabajo en Delphi. He visto varias aplicaciones basadas en sqlite de Windows que realizan SELECT (y creo que ORDER BY) insensible a mayúsculas y minúsculas, independientemente de si están instaladas en una configuración polaca en inglés, alemán o (en mi caso) polaco. Prueba Firefox :) ¿Cómo lo hacen? –
Normalmente incorrecto :) Polaco tiene IIRC sin casos difíciles; todos los caracteres no ASCII utilizados en polaco están "basados en" caracteres ASCII. – MSalters
Excepto por el problema Turco I, el algoritmo Unicode Case Folding (http://www.unicode.org/reports/tr44/) funciona notablemente bien. – dalle