Pregunta C ++ multiplataforma: ¿utiliza la codificación de cadena nativa o estandariza en todas las plataformas?


Estamos buscando específicamente el desarrollo de Windows y Linux, y hemos presentado dos enfoques diferentes que parecen tener sus méritos. El tipo de cadena Unicode natural en Windows es UTF-16 y UTF-8 en Linux.

No podemos decidir si el mejor enfoque es:

  1. Estandarice uno de los dos en toda nuestra lógica de aplicaciones (y datos persistentes) y haga que las otras plataformas realicen las conversiones adecuadas

  2. Utilice el formato natural para el sistema operativo para la lógica de la aplicación (y, por lo tanto, realice llamadas al sistema operativo), y convierta solo en el punto de IPC y persistencia.

Para mí, parece que ambos son tan buenos como los demás.


10
2018-04-02 09:29


origen


Respuestas:


y UTF-8 en Linux.

Es mayormente cierto para Linux moderno. En realidad, la codificación depende de qué API o biblioteca se use. Algunos hardcoded para usar UTF-8. Pero algunos leen las variables de entorno LC_ALL, LC_CTYPE o LANG para detectar la codificación a usar (como la biblioteca Qt). Así que ten cuidado.

No podemos decidir si el mejor enfoque

Como de costumbre, depende.

Si el 90% del código es para tratar con la API específica de la plataforma de una manera específica de la plataforma, obviamente es mejor usar cadenas específicas de la plataforma. Como ejemplo: un controlador de dispositivo o una aplicación nativa de iOS.

Si el 90% del código es una lógica comercial compleja que se comparte entre plataformas, obviamente es mejor usar la misma codificación en todas las plataformas. Como ejemplo: cliente de chat o navegador.

En el segundo caso, tienes una opción:

  • Utilice la biblioteca multiplataforma que proporciona soporte de cadenas (Qt, ICU, por ejemplo)
  • Utilice punteros simples (considero que std :: string es un "puntero descubierto" también)

Si trabajar con cadenas es una parte importante de su aplicación, elegir una buena biblioteca para cadenas es una buena jugada. Por ejemplo, Qt tiene un conjunto muy sólido de clases que cubre el 99% de las tareas comunes. Desafortunadamente, no tengo experiencia en la unidad de cuidados intensivos, pero también se ve muy bien.

Cuando se utiliza una biblioteca para cadenas, debe preocuparse por la codificación solo cuando se trabaja con bibliotecas externas, plataforma API o envío de cadenas a través de la red (o disco). Por ejemplo, muchos programadores de Cocoa, C # o Qt (todos tienen soporte para cadenas sólidas) saben muy poco sobre los detalles de codificación (y es bueno, ya que pueden enfocarse en su tarea principal).

Mi experiencia trabajando con cuerdas es una pequeño específico, así que personalmente prefiero los indicadores simples. El código que los usa es muy portátil (en el sentido de que puede reutilizarse fácilmente en otros proyectos y plataformas) porque tiene menos dependencias externas. Es extremadamente simple y rápido también (pero uno probablemente necesite algo de experiencia y de fondo Unicode para sentir eso).

Estoy de acuerdo en que el enfoque de los indicadores simples no es para todos. Es bueno cuando:

  • Trabajas con cadenas enteras y dividir, buscar, comparar es una tarea rara
  • Puede usar la misma codificación en todos los componentes y necesita una conversión solo cuando usa la plataforma API
  • Todas las plataformas compatibles tienen API para:
    • Convertir desde su codificación a eso se usa en API
    • Convertir de la codificación API a la que se usa en su código
  • Punteros no es un problema en tu equipo

De mi a pequeño experiencia específica es en realidad un caso muy común.

Al trabajar con punteros simples, es bueno elegir la codificación que se usará en todo el proyecto (o en todos los proyectos).

Desde mi punto de vista, UTF-8 es un ganador final. Si no puede usar UTF-8 - use la biblioteca de cadenas o API de plataforma para cadenas - le ahorrará mucho tiempo.

Ventajas de UTF-8:

  • Completamente compatible con ASCII. Cualquier cadena ASCII es una cadena UTF-8 válida.
  • La biblioteca C std funciona muy bien con cadenas UTF-8. (*)
  • La biblioteca C ++ std funciona muy bien con UTF-8 (std :: string y friends). (*)
  • El código heredado funciona muy bien con UTF-8.
  • Cualquier plataforma admite UTF-8.
  • La depuración es MUCHO más fácil con UTF-8 (ya que es compatible con ASCII).
  • No es un desastre Little Little Endian / Big Endian.
  • No detectará un error clásico "Oh, UTF-16 no siempre tiene 2 bytes".

(*) Hasta que tenga que compararlos léxicamente, transformar el caso (toUpper / toLower), cambiar el formulario de normalización o algo así - si lo hace - use la biblioteca de cadenas o la plataforma API.

La desventaja es cuestionable:

  • Menos compacto para chino (y otros símbolos con grandes números de punto de código) que UTF-16.
  • Más difícil (un poco en realidad) para iterar sobre los símbolos.

Por lo tanto, recomiendo usar UTF-8 como codificación común para los proyectos que no usan ninguna biblioteca de cadenas.

Pero la codificación no es la única pregunta que debes responder.

Hay tal cosa como normalización. Para decirlo de manera simple, algunas letras se pueden representar de varias maneras, como un glifo o como una combinación de diferentes glifos. El problema común con esto es que la mayoría de las funciones de comparación de cadenas las tratan como símbolos diferentes. Si trabaja en proyectos multiplataforma, elegir uno de los formularios de normalización como estándar es un paso correcto. Esto te ahorrará tiempo.

Por ejemplo, si la contraseña del usuario contiene "йёжиг" se representará de manera diferente (en UTF-8 y UTF-16) cuando se ingrese en Mac (que usa principalmente el Formulario de normalización D) y en Windows (que más le gusta el Formulario de normalización C). Por lo tanto, si el usuario se registra en Windows con dicha contraseña, tendrá un problema para iniciar sesión en Mac.

Además, no recomendaría usar wchar_t (ni usarlo solo en el código de Windows como tipo de carácter UCS-2 / UTF-16). El problema con wchar_t es que no hay codificación asociada con él. Es solo un char ancho abstracto que es más grande que el char normal (16 bits en Windows, 32 bits en la mayoría * nix).


6
2017-08-24 18:42



Usaría la misma codificación internamente y normalizaría los datos en el punto de entrada. Esto implicará menos código, menos errores, y le permitirá usar la misma biblioteca multiplataforma para el procesamiento de cadenas.

Usaría unicode (utf-16) porque es más sencillo de manejar internamente y debería funcionar mejor debido a la longitud constante de cada carácter. UTF-8 es ideal para salida y almacenamiento porque es compatible con latin ascii y usa 8 bits para caracteres ingleses. Pero dentro del programa de 16 bits es más fácil de manejar.


0
2018-04-02 09:36



C ++ 11 proporciona los nuevos tipos de cadenas u16string y u32string. Dependiendo del soporte que entreguen las versiones de su compilador, y la esperanza de vida esperada, podría ser una idea para mantenerse compatible con versiones anteriores.

Aparte de eso, usando el UCI la biblioteca es probablemente la mejor opción para la compatibilidad multiplataforma.


0
2018-06-06 17:14



Esto parece ser bastante esclarecedor sobre el tema. http://www.utf8everywhere.org/


0
2017-09-12 02:32



La programación con UTF-8 es difícil ya que las longitudes y los desplazamientos se mezclan. p.ej.

    std::string s = Something();
    std::cout << s.substr(0, 4);

no necesariamente encuentra los primeros 4 caracteres.

Yo usaría cualquier cosa wchar_t es. En Windows que será UTF-16. En algunas plataformas * nix podría ser UTF-32.

Al guardar en un archivo, recomendaría convertir a UTF-8. Eso a menudo hace que el archivo sea más pequeño y elimina las dependencias de la plataforma debido a las diferencias en sizeof(wchar_t) o para ordenar byte.


-1
2018-06-06 17:06



Preguntas populares