Saltar al contenido

char vs wchar_t cuándo usar qué tipo de datos

Estate atento ya que en esta noticia vas a encontrar la solución que buscas.Este escrito ha sido analizado por nuestros especialistas para garantizar la calidad y exactitud de nuestro post.

Solución:

Respuesta corta:

Nunca debes usar wchar_t en C++ moderno, excepto cuando interactúa con API específicas del sistema operativo (básicamente usa wchar_t solo para llamar a las funciones de la API de Windows).

Respuesta larga:

El diseño de la biblioteca estándar de C++ implica que solo hay una forma de manejar Unicode: almacenando cadenas codificadas en UTF-8 en matrices de caracteres, ya que casi todas las funciones existen solo en variantes de caracteres (piense en std::exception::what).

En un programa C++ tienes dos configuraciones regionales:

  • Configuración regional estándar de la biblioteca C establecida por std::setlocale
  • Configuración regional estándar de la biblioteca de C++ establecida por std::locale::global

Desafortunadamente, ninguno de ellos define el comportamiento de las funciones estándar que abren archivos (como std::fopen, std::fstream::open etc.). El comportamiento difiere entre los sistemas operativos:

  • Linux es independiente de la codificación, por lo que esas funciones simplemente pasan char string a la llamada del sistema subyacente
  • En el carácter de Windows string se convierte en ancho string utilizando la configuración regional específica del usuario antes de realizar la llamada al sistema

Por lo general, todo funciona bien en Linux, ya que todos usan configuraciones regionales basadas en UTF-8, por lo que todas las entradas y argumentos del usuario pasan a main Las funciones estarán codificadas en UTF-8. Pero es posible que aún deba cambiar las configuraciones regionales actuales a las variantes UTF-8 explícitamente, ya que, de manera predeterminada, el programa C ++ comienza a usar el valor predeterminado "C" lugar. En este punto, si solo le interesa Linux y no necesita compatibilidad con Windows, puede usar matrices de caracteres y std::string asumiendo que son secuencias UTF-8 y todo “simplemente funciona”.

Los problemas aparecen cuando desea admitir Windows, ya que allí siempre tiene una tercera configuración regional adicional: la configurada para el usuario actual que se puede configurar en algún lugar del “Panel de control”. El problema principal es que esta configuración regional nunca es una configuración regional Unicode, por lo que es imposible usar funciones como std::fopen(const char *) y std::fstream::open(const char *) para abrir un archivo utilizando la ruta Unicode. En Windows, tendrá que usar envoltorios personalizados que usan funciones específicas de Windows no estándar como _wfopen, std::fstream::open(const wchar_t *) en Windows Puede consultar Boost.Nowide (aún no incluido en Boost) para ver cómo se puede hacer esto: http://cppcms.com/files/nowide/html/

Con C++ 17 puedes usar std::filesystem::path para almacenar la ruta del archivo de forma portátil, pero aún no funciona en Windows:

  • Constructor implícito std::filesystem::path::path(const char *) usa la configuración regional específica del usuario en MSVC y no hay forma de hacer que use UTF-8. Función std::filesystem::u8string debe usarse para construir una ruta desde UTF-8 stringpero es demasiado fácil olvidarse de esto y usar una construcción implícita en su lugar.
  • std::error_category::message(int) para ambas categorías de error devuelve la descripción del error utilizando la codificación específica del usuario.

Así que lo que tenemos en Windows es:

  • Las funciones de biblioteca estándar que abren archivos están rotas y nunca deben usarse.
  • Argumentos pasados ​​a main(int, char**) están rotas y nunca deben usarse.
  • Las funciones de WinAPI que terminan en *A y las macros no funcionan y nunca deben usarse.
  • std::filesystem::path está parcialmente roto y nunca debe usarse directamente.
  • Categorías de error devueltas por std::generic_category y std::system_category están rotas y nunca deben usarse.

Si necesita una solución a largo plazo para un proyecto no trivial, le recomendaría:

  • Usando Boost.Nowide o implementando una funcionalidad similar directamente: esta biblioteca estándar rota fija.
  • Reimplementación de las categorías de error estándar devueltas por std::generic_category y std::system_category para que siempre devuelvan cadenas codificadas en UTF-8.
  • Envase std::filesystem::path para que la nueva clase siempre use UTF-8 al convertir la ruta a string y string camino
  • Envolviendo todas las funciones requeridas de std::filesystem para que usen su contenedor de ruta y sus categorías de error.

Desafortunadamente, esto no solucionará los problemas con otras bibliotecas que funcionan con archivos, pero el 99% de ellas están rotas de todos modos (no son compatibles con Unicode).

Así es la vida de un programador de C++. Microsoft podría solucionar esto permitiéndonos cambiar el tiempo de ejecución de Windows a la configuración regional basada en UTF-8, pero no lo harán debido a la compatibilidad con versiones anteriores.

Puede consultar este enlace para obtener más explicaciones: http://utf8everywhere.org/

Fundamentalmente, utiliza wchar_t cuando la codificación tiene más símbolos que un char puede contener

Antecedentes

los char type tiene capacidad suficiente para contener cualquier carácter (codificación) en el juego de caracteres ASCII.

El problema es que muchos idiomas requieren más codificaciones que las cuentas ASCII. Entonces, en lugar de 127 codificaciones posibles, se necesitan más. Algunos idiomas tienen más de 256 codificaciones posibles. A char type no garantiza un rango superior a 256. Por lo tanto, se requiere un nuevo tipo de datos.

los wchar_ttambién conocido como caracteres anchos, proporciona más espacio para codificaciones.

Resumen

Utilizar char tipo de datos cuando el rango de codificaciones es 256 o menos, como ASCII. Utilizar wchar_t cuando necesite capacidad para más de 256.

Prefiere Unicode para manejar juegos de caracteres grandes (como emojis).

Nunca usar wchar_t.

Cuando sea posible, use (algún tipo de array de) chartal como std::stringy asegúrese de que esté codificado en UTF-8.

Cuando deba interactuar con API que no hablan UTF-8, use char16_t o char32_t. Nunca los use de otra manera; solo brindan ventajas ilusorias y fomentan el código defectuoso.

Tenga en cuenta que hay mucho de los casos en que más de una char32_t se requiere para representar un solo carácter visible para el usuario. OTOH, usando UTF-8 con char te obliga a manejar el ancho variable muy temprano.

Sección de Reseñas y Valoraciones

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *