Antes de continuar, debo mencionar que lo que está haciendo no es compatible con C/C++. El specification indica en 2.2 qué conjuntos de caracteres son válidos en el código fuente. No hay mucho allí, y todos los personajes utilizados están en ascii. Entonces ... Todo a continuación es sobre una implementación específica (como ocurre, VC2008 en una máquina local de EE. UU.).
Para empezar, tiene 4 caracteres en su línea cout
, y 4 glifos en la salida. Por lo tanto, el problema no es la codificación UTF8, ya que combinaría varios caracteres fuente en menos glifos.
De ti cadena de origen a la pantalla de la consola, todas esas cosas juegan un papel importante:
- Lo que codifica el archivo de origen está en (es decir, cómo el archivo de C++ será visto por el compilador)
- lo que su compilador hace con una cadena literal, y qué fuente que lo codifica entiende
- cómo su
<<
interpreta la cadena codificada que está pasando en
- lo codifica la consola de espera
- cómo la consola traduce esa salida a un glifo de fuente.
Ahora ...
1 y 2 son bastante fáciles. Parece que el compilador adivina en qué formato se encuentra el archivo fuente y lo decodifica en su representación interna. Genera el literal de cadena correspondiente a la porción de datos en la página de códigos actual independientemente de la codificación de origen. No he podido encontrar detalles/control explícitos sobre esto.
3 es aún más fácil. A excepción de los códigos de control, <<
simplemente pasa los datos por char *.
4 es controlado por SetConsoleOutputCP
. Debería establecerse de forma predeterminada en la página de códigos predeterminada del sistema. También puede averiguar cuál tiene con GetConsoleOutputCP
(la entrada se controla de manera diferente, a través de SetConsoleCP
)
5 es divertido. Me golpeé la cabeza para descubrir por qué no podía hacer que el é se mostrara correctamente, usando CP1252 (europeo occidental, Windows). Resulta que la fuente de mi sistema no tiene el glifo para ese personaje, y usa útilmente el glifo de mi página de códigos estándar (mayúscula Theta, lo mismo que obtendría si no llamara a SetConsoleOutputCP). Para solucionarlo, tuve que cambiar la fuente que uso en las consolas a Lucida Console (una verdadera tipografía).
Algunas cosas interesantes que aprendí mirando esto:
- la codificación de la fuente no importa, siempre y cuando el compilador puede averiguarlo (en particular, cambiándolo a UTF8 no cambió el código generado . Mi cadena "é" aún estaba codificada con CP1252 como
233 0
)
- VC está seleccionando una página de códigos para los literales de cadenas que no parecen controlar.
- controlando lo que muestra la consola es más doloroso que lo que estaba esperando
Así que ... ¿qué significa esto para usted? Estos son algunos consejos:
- no utilice non-ascii en cadenas literales. Use los recursos, donde usted controla la codificación.
- asegúrate de saber qué codificación espera la consola y que tu fuente tenga los glifos para representar los caracteres que envíes.
- si desea saber qué codificación se está utilizando en su caso, le aconsejo que imprima el valor real del carácter como un número entero.
char * a = "é"; std::cout << (unsigned int) (unsigned char) a[0]
muestra 233 para mí, que es la codificación en CP1252.
Por cierto, si lo que se obtuvo fue "Ouu" en lugar de lo que ha pegado, entonces parece que los 4 bytes se interpretan como un lugar CP850.
¿Nos puede dar un poco más de entrada. ¿Esto está sucediendo para la producción de compilación, todos los resultados o algo más? ¿Puede darnos una operación específica para la que esto sucede (creación, depuración, etc.) – JaredPar
Sí, muestre un ejemplo de lo que cree que debería aparecer y lo que realmente aparece. – wallyk
¿Qué sucede si usa wcout? – Naveen