Funciones, Strings... Unicode. C++

Iniciado por Matias Juarez, 29 Noviembre 2016, 02:32 AM

0 Miembros y 1 Visitante están viendo este tema.

Matias Juarez

Alguien podrían orientarme un poco, hace poco empece con un curso de c++ por lo que mis conocimientos son semi-nulos.
Estoy usando Code::Blocks y no entiendo como hacer para trabajar con cadenas unicode, me tira errores, en todo, no entiendo como funciona...
Por ejemplo, esta función trabaja correctamente:
Código (cpp) [Seleccionar]
MessageBoxA(0, "Texto", "Título", MB_OK | MB_ICONINFORMATION);
Pero esta no!!:
Código (cpp) [Seleccionar]
MessageBoxW(0, "Texto", "Título", MB_OK | MB_ICONINFORMATION);
/* MessageBoxW(0, L"Texto", "Título", MB_OK | MB_ICONINFORMATION); */

Mis preguntas mas concretas serían:
1) ¿Por que pasa esto?, ¿cual es el problema?, ¿para que sirve la 'L', por ejemplo: 'L"string"'.
2) ¿como declaro y uso una variable de tipo LPWSTR?
3) ¿por que Code::Blocks usa Ansi por defecto (o tal vez tiene que ver el compilador)?, ¿por que no se muestra el texto que contiene caracteres, por ejemplo, acentuados (hablo del uso de, por ejemplo, con 'cout')?. He intentado usar SetConsoleOutputCP() entre otras cosas, y no parece tener ningún efecto, lo único que me ha servido es usar:
Código (cpp) [Seleccionar]
_setmode(_fileno(stdout), 0x20000); // _O_U16TEXT = 0x20000
_setmode(_fileno(stdin), 0x20000); // _O_U16TEXT = 0x20000

Pero parece interferir con otras cosas, no es lo que busco, creo.
4) ¿cual es la diferencia entre wchar_t, char32_t, WCHAR, TCHAR?, ¿cual debo usar?.
5) ¿debo tener en cuenta algo al ejecutar mi programa en otra versión de Windows (sobre este tema)?.
6) ¿como convierto entre una página de códigos a otra?, ¿cual me recomiendan usar y como?.

Gracias!

ivancea96

Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
1) ¿Por que pasa esto?, ¿cual es el problema?, ¿para que sirve la 'L', por ejemplo: 'L"string"'.
MessageBoxW requiere wide-chars (wchar_t), al finy  al cabo, es para lo que funciona. Los parámetros deben ser "wide char":
Código (cpp) [Seleccionar]
MessageBoxW(0, L"Texto", L"Título", MB_OK | MB_ICONINFORMATION);
Ambos. La 'L' implica que una cadena en vez de ser char*, es wchar_t*.

Interesante ver que el código, para utilizar bien los L"", debe estar en una codificación diferente a ANSI (UTF-8, por ejemplo).


Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
2) ¿como declaro y uso una variable de tipo LPWSTR?
L"texto" es una LPWSTR. wchar_t* o WCHAR*. Son lo mismo.
LPWSTR == Pointer to Wide String
LPCWSTR == Pointer to Constant Wide String

La diferencia entre estos tipos y char es que wchar_t suele ser de mayor tamaño que char. (char -> 1 byte, wchar_t -> 2 bytes)
También existen char16_t y char32_t, como curiosidad.


Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
4) ¿cual es la diferencia entre wchar_t, char32_t, WCHAR, TCHAR?, ¿cual debo usar?.
En caso de querer información sobre un tipo, tienes varias opciones.
Una rápida es forzar un error, y el compilador te suele decir qué tipos son:
Código (cpp) [Seleccionar]
TCHAR c = "error";
error: invalid conversion from 'const char*' to 'TCHAR {aka char}'
Ahí ya nos dice que TCHAR es un char.

Otra opción, dado que son tipos de Windows, es visitar sus referencias:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
Ahí explica qué es TCHAR:
Código (cpp) [Seleccionar]
#ifdef UNICODE
    typedef WCHAR TCHAR;
#else
    typedef char TCHAR;
#endif


Y finalmente, otra:
Código (cpp) [Seleccionar]
#include <windows.h>
#include <typeinfo>

int main(){
cout << typeid(TCHAR).name() << endl;
}

Ese nombre a veces no es muy descriptivo. Pero puedes comparar nombres. Si 2 nombres son iguales, los tipos son iguales.
Si no te interesa el nombre, puedes hacer una comparación directa:
Código (cpp) [Seleccionar]
cout << (typeid(TCHAR) == typeid(char)) << endl;


Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
3) ¿por que Code::Blocks usa Ansi por defecto (o tal vez tiene que ver el compilador)?, ¿por que no se muestra el texto que contiene caracteres, por ejemplo, acentuados (hablo del uso de, por ejemplo, con 'cout')?.

Code::Blocks -> Settings -> Editor -> Other Settings
Ahí elijes codificación.
En el caso de mi compilador, utiliza OEM-850 (u otro parecido, no me fijé)


Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
5) ¿debo tener en cuenta algo al ejecutar mi programa en otra versión de Windows (sobre este tema)?.
En principio no. De existir algún problema, nunca me ha ocurrido.

Cita de: Flipeador2016 en 29 Noviembre 2016, 02:32 AM
6) ¿como convierto entre una página de códigos a otra?, ¿cual me recomiendan usar y como?.
Estas dos funciones te pueden ayudar:
MultiByteToWideChar
WideCharToMultiByte

Matias Juarez

Perfecto, gracias ivancea96 me has sacado todas las dudas sobre este tema  ;-) .