Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Matias Juarez en 29 Noviembre 2016, 02:32 am



Título: Funciones, Strings... Unicode. C++
Publicado por: Matias Juarez en 29 Noviembre 2016, 02:32 am
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
  1. MessageBoxA(0, "Texto", "Título", MB_OK | MB_ICONINFORMATION);
Pero esta no!!:
Código
  1. MessageBoxW(0, "Texto", "Título", MB_OK | MB_ICONINFORMATION);
  2. /* 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
  1. _setmode(_fileno(stdout), 0x20000); // _O_U16TEXT = 0x20000
  2. _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!


Título: Re: Funciones, Strings... Unicode. C++
Publicado por: ivancea96 en 29 Noviembre 2016, 16:27 pm
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
  1. 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).


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.


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
  1. TCHAR c = "error";
Código:
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 (https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx)
Ahí explica qué es TCHAR:
Código
  1. #ifdef UNICODE
  2.    typedef WCHAR TCHAR;
  3. #else
  4.    typedef char TCHAR;
  5. #endif

Y finalmente, otra:
Código
  1. #include <windows.h>
  2. #include <typeinfo>
  3.  
  4. int main(){
  5. cout << typeid(TCHAR).name() << endl;
  6. }
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
  1. cout << (typeid(TCHAR) == typeid(char)) << endl;


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é)


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.

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 (https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx)
WideCharToMultiByte (https://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx)


Título: Re: Funciones, Strings... Unicode. C++
Publicado por: Matias Juarez en 29 Noviembre 2016, 18:25 pm
Perfecto, gracias ivancea96 me has sacado todas las dudas sobre este tema  ;-) .