x64 visual sp1 microsoft descargar c++ visual-c++ utf-8

sp1 - microsoft visual c++ 2012 redistributable package(x64)



Cómo crear un literal de cadena UTF-8 en Visual C++ 2008 (17)

¿Qué tal esto? Almacena las cadenas en un archivo codificado en UTF-8 y luego las preprocesa en un archivo fuente en C ++ codificado en ASCII. Mantiene la codificación UTF-8 dentro de la cadena mediante el uso de escapes hexadecimales. La cuerda

"中国語 (繁体)"

se convierte a

"/xE4/xB8/xAD/xE5/x9B/xBD/xE8/xAA/x9E (/xE7/xB9/x81/xE4/xBD/x93)"

Por supuesto, esto es ilegible para cualquier ser humano, y el propósito es simplemente evitar problemas con el compilador.

Puede usar el preprocesador C ++ para hacer referencia a las cadenas en el archivo de encabezado convertido o puede convertir todo el origen UTF-8 en ASCII antes de la compilación usando este truco.

En VC ++ 2003, pude simplemente guardar el archivo de origen como UTF-8 y todas las cadenas se usaron tal cual. En otras palabras, el siguiente código imprimirá las cadenas tal cual a la consola. Si el archivo fuente se guardó como UTF-8, entonces la salida sería UTF-8.

printf("Chinese (Traditional)"); printf("中国語 (繁体)"); printf("중국어 (번체)"); printf("Chinês (Tradicional)");

He guardado el archivo en formato UTF-8 con la BOM UTF-8. Sin embargo, compilar con VC2008 da como resultado:

warning C4566: character represented by universal-character-name ''/uC911'' cannot be represented in the current code page (932) warning C4566: character represented by universal-character-name ''/uAD6D'' cannot be represented in the current code page (932) etc.

Los caracteres que causan estas advertencias están dañados. Los que encajan en la configuración regional (en este caso 932 = japonés) se convierten a la codificación de configuración regional, es decir, Shift-JIS.

No puedo encontrar una manera de hacer que VC ++ 2008 compile esto para mí. Tenga en cuenta que no importa qué configuración regional utilizo en el archivo fuente. No parece haber una configuración regional que diga "Sé lo que estoy haciendo, así que no f $% ## ng cambie mis literales de cadena". En particular, la pseudo-locación UTF-8 inútil no funciona.

#pragma setlocale(".65001") => error C2175: ''.65001'' : invalid locale

Tampoco "C":

#pragma setlocale("C") => see warnings above (in particular locale is still 932)

Parece que VC2008 obliga a todos los caracteres a la configuración regional especificada (o predeterminada), y esa configuración regional no puede ser UTF-8. No quiero cambiar el archivo para usar cadenas de escape como "/ xbf / x11 ..." porque la misma fuente se compila usando gcc, que puede tratar bastante felizmente con los archivos UTF-8.

¿Hay alguna forma de especificar que la compilación del archivo fuente debe dejar intactos los literales de cadena?

Para plantearlo de otra manera, ¿qué indicadores de compilación puedo usar para especificar la compatibilidad con VC2003 al compilar el archivo fuente? es decir, no modifiques los literales de cadena, utilízalos byte para byte tal como están.

Actualizar

Gracias por las sugerencias, pero quiero evitar el wchar. Dado que esta aplicación se ocupa de cadenas en UTF-8 exclusivamente, el uso de wchar me obligará a convertir todas las cadenas de nuevo en UTF-8, lo que debería ser innecesario. Toda la entrada, salida y procesamiento interno está en UTF-8. Es una aplicación simple que funciona bien en Linux y cuando se compila con VC2003. Quiero poder compilar la misma aplicación con VC2008 y hacer que funcione.

Para que esto suceda, necesito el VC2008 para no intentar convertirlo a la configuración regional de mi máquina local (japonés, 932). Quiero que el VC2008 sea retrocompatible con el VC2003. Quiero una configuración regional o compiladora que diga que las cadenas se usan como son, esencialmente como matrices opacas de char, o como UTF-8. Parece que podría estar atrapado con VC2003 y gcc sin embargo, VC2008 está tratando de ser demasiado inteligente en este caso.


Actualizar:

He decidido que no hay una manera garantizada de hacer esto. La solución que presento a continuación funciona para la versión en inglés VC2003, pero falla al compilar con la versión japonesa VC2003 (o tal vez es el sistema operativo japonés). En cualquier caso, no se puede depender de que funcione. Tenga en cuenta que incluso declarar todo como L "" cadenas no funcionó (y es doloroso en gcc como se describe a continuación).

En cambio, creo que solo necesita morder la bala y mover todo el texto a un archivo de datos y cargarlo desde allí. Ahora estoy almacenando y accediendo al texto en archivos INI a través de SimpleIni (biblioteca de archivos INI multiplataforma). Al menos hay una garantía de que funciona ya que todo el texto está fuera del programa.

Original:

Estoy respondiendo yo mismo, ya que solo Evan parecía comprender el problema. Las respuestas con respecto a qué es Unicode y cómo usar wchar_t no son relevantes para este problema, ya que no se trata de internacionalización, ni de un malentendido de Unicode, codificaciones de caracteres. Aunque aprecio tu intento de ayudar, disculpas si no fui lo suficientemente claro.

El problema es que tengo archivos fuente que deben compilarse de forma cruzada en una variedad de plataformas y compiladores. El programa realiza el procesamiento UTF-8. No le importan otras codificaciones. Quiero tener literales de cadena en UTF-8, como actualmente funciona con gcc y vc2003. ¿Cómo lo hago con VC2008? (es decir, solución compatible con versiones anteriores).

Esto es lo que he encontrado:

gcc (v4.3.2 20081105):

  • los literales de cadena se usan como son (cadenas sin formato)
  • admite archivos fuente codificados UTF-8
  • los archivos fuente no deben tener una BOM UTF-8

vc2003:

  • los literales de cadena se usan como son (cadenas sin formato)
  • admite archivos fuente codificados UTF-8
  • los archivos fuente pueden o no tener una lista de materiales UTF-8 (no importa)

vc2005 +:

  • el compilador masajea los literales de cadena (sin cadenas en bruto)
  • Los literales de cadena char se recodifican a una configuración regional especificada
  • UTF-8 no es compatible como una configuración regional de destino
  • los archivos fuente deben tener una BOM UTF-8

Entonces, la respuesta simple es que para este propósito particular, VC2005 + está roto y no proporciona una ruta de compilación compatible con versiones anteriores. La única forma de obtener cadenas Unicode en el programa compilado es a través de UTF-8 + BOM + wchar, lo que significa que tengo que convertir todas las cadenas de nuevo a UTF-8 en el momento del uso.

No existe un método simple multiplataforma de conversión de wchar a UTF-8, por ejemplo, ¿qué tamaño y codificación tiene el wchar? En Windows, UTF-16. En otras plataformas? Varía. Vea el proyecto de ICU para algunos detalles.

Al final, decidí que evitaría el costo de conversión en todos los compiladores que no sean vc2005 + con una fuente como la siguiente.

#if defined(_MSC_VER) && _MSC_VER > 1310 // Visual C++ 2005 and later require the source files in UTF-8, and all strings // to be encoded as wchar_t otherwise the strings will be converted into the // local multibyte encoding and cause errors. To use a wchar_t as UTF-8, these // strings then need to be convert back to UTF-8. This function is just a rough // example of how to do this. # define utf8(str) ConvertToUTF8(L##str) const char * ConvertToUTF8(const wchar_t * pStr) { static char szBuf[1024]; WideCharToMultiByte(CP_UTF8, 0, pStr, -1, szBuf, sizeof(szBuf), NULL, NULL); return szBuf; } #else // Visual C++ 2003 and gcc will use the string literals as is, so the files // should be saved as UTF-8. gcc requires the files to not have a UTF-8 BOM. # define utf8(str) str #endif

Tenga en cuenta que este código es solo un ejemplo simplificado. El uso de la producción necesitaría limpiarlo de diversas maneras (seguridad de hilos, comprobación de errores, comprobaciones del tamaño del búfer, etc.).

Esto se usa como el siguiente código. Se compila de forma limpia y funciona correctamente en mis pruebas en gcc, vc2003 y vc2008:

std::string mText; mText = utf8("Chinese (Traditional)"); mText = utf8("中国語 (繁体)"); mText = utf8("중국어 (번체)"); mText = utf8("Chinês (Tradicional)");


Archivo / Opciones de guardado avanzado / Codificación: "Unicode (UTF-8 sin firma ) - Página de códigos 65001"


Archivos fuente UTF-8

  • Sin BOM : se tratan como sin formato, excepto si el sistema usa> 1byte / char codepage (como Shift JIS). Necesita cambiar la página de códigos del sistema a cualquier byte único y luego debería poder usar caracteres Unicode dentro de los literales y compilar sin problemas (al menos eso espero).
  • Con BOM : tienen char y literales de cadena convertidos a la página de códigos del sistema durante la compilación. Puede verificar la página de códigos del sistema actual con GetACP (). AFAIK, no hay forma de configurar la página de códigos del sistema en 65001 (UTF-8), por lo tanto, no hay forma de usar UTF-8 directamente con BOM.

La única forma independiente de compilador y portátil es utilizar conjuntos de caracteres ASCII y secuencias de escape, porque no hay garantías de que cualquier compilador acepte archivos codificados en UTF-8.


Brofield,

Tuve exactamente el mismo problema y me encontré con una solución que no requiere la conversión de cadenas fuente a caracteres anchos y viceversa: guarde su archivo fuente como UTF-8 sin firma y VC2008 lo dejará en paz. Funcionó muy bien cuando descubrí que soltar la firma. Para resumir:

Unicode (UTF-8 sin firma) - Codepage 65001, no arroja la advertencia c4566 en VC2008 y no hace que VC se meta con la codificación, mientras que Codepage 65001 (UTF-8 With Signature) arroja c4566 (como lo ha hecho encontró).

Espero que no sea demasiado tarde para ayudarlo, pero podría acelerar su aplicación VC2008 para eliminar su solución alternativa.



El comportamiento estándar de COMPILER de Visual C ++ (2005+) para los archivos fuente es:

  • CP1252 (para este ejemplo, página de códigos de Europa occidental):
    • "Ä"C4 00
    • ''Ä''C4
    • L"Ä"00C4 0000
    • L''Ä''00C4
  • UTF-8 sin BOM:
    • "Ä"C3 84 00 (= UTF-8)
    • ''Ä'' → advertencia: constante de caracteres múltiples
    • "Ω"E2 84 A6 00 (= UTF-8, como se esperaba)
    • L"A"00C3 0084 0000 (¡incorrecto!)
    • L''Ä'' → advertencia: constante de varios caracteres
    • L"Ω"00E2 0084 00A6 0000 (¡incorrecto!)
  • UTF-8 con BOM:
    • "Ä"C4 00 (= CP1252, no más UTF-8),
    • ''Ä''C4
    • "Ω" → error: ¡no se puede convertir a CP1252!
    • L"Ä"00C4 0000 (correcto)
    • L''Ä''00C4
    • L"Ω"2126 0000 (correcto)

Verá, el compilador de C maneja los archivos UTF-8 sin BOM de la misma manera que CP1252. Como resultado, es imposible que el compilador mezcle cadenas UTF-8 y UTF-16 en la salida compilada. Entonces debes decidir por un archivo de código fuente:

  • use UTF-8 con BOM y genere cadenas UTF-16 solamente (es decir, siempre use el prefijo L ),
  • o UTF-8 sin BOM y solo genera cadenas UTF-8 (es decir, nunca use el prefijo L ).
  • Los caracteres ASCII de 7 bits no están involucrados y se pueden usar con o sin el prefijo L

Independientemente, el EDITOR puede detectar automáticamente archivos UTF-8 sin BOM como archivos UTF-8.


Entonces, cosas para cambiar Ahora tengo una solución.

En primer lugar, debe ejecutar en la página local de código de byte único, como el inglés, para que cl.exe no consiga que los códigos lleguen a ser un caos.

Segundo, guarde el código fuente en UTF8-NO BOM, observe NO-BOM, y luego compile con cl.exe, NO llame a ninguna API de C, como printf wprint, todo ese personal no funciona, no lo hago No sé por qué:) .... puede tener un estudio más tarde ...

Luego solo compila y ejecuta, verás el resultado ... mi correo electrónico es luoyonggang, (Google) espero algo ......

wscript:

#! /usr/bin/env python # encoding: utf-8 # Yonggang Luo # the following two variables are used by the target "waf dist" VERSION=''0.0.1'' APPNAME=''cc_test'' top = ''.'' import waflib.Configure def options(opt): opt.load(''compiler_c'') def configure(conf): conf.load(''compiler_c'') conf.check_lib_msvc(''gdi32'') conf.check_libs_msvc(''kernel32 user32'') def build(bld): bld.program( features = ''c'', source = ''chinese-utf8-no-bom.c'', includes = ''. ..'', cflags = [''/wd4819''], target = ''myprogram'', use = ''KERNEL32 USER32 GDI32'')

Ejecutando el script run.bat

rd /s /q build waf configure build --msvc_version "msvc 6.0" build/myprogram rd /s /q build waf configure build --msvc_version "msvc 9.0" build/myprogram rd /s /q build waf configure build --msvc_version "msvc 10.0" build/myprogram

Código fuente main.c:

//encoding : utf8 no-bom #include <stdio.h> #include <string.h> #include <Windows.h> char* ConvertFromUtf16ToUtf8(const wchar_t *wstr) { int requiredSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, 0, 0, 0, 0); if(requiredSize > 0) { char *buffer = malloc(requiredSize + 1); buffer[requiredSize] = 0; WideCharToMultiByte(CP_UTF8, 0, wstr, -1, buffer, requiredSize, 0, 0); return buffer; } return NULL; } wchar_t* ConvertFromUtf8ToUtf16(const char *cstr) { int requiredSize = MultiByteToWideChar(CP_UTF8, 0, cstr, -1, 0, 0); if(requiredSize > 0) { wchar_t *buffer = malloc( (requiredSize + 1) * sizeof(wchar_t) ); printf("converted size is %d 0x%x/n", requiredSize, buffer); buffer[requiredSize] = 0; MultiByteToWideChar(CP_UTF8, 0, cstr, -1, buffer, requiredSize); printf("Finished/n"); return buffer; } printf("Convert failed/n"); return NULL; } void ShowUtf8LiteralString(char const *name, char const *str) { int i = 0; wchar_t *name_w = ConvertFromUtf8ToUtf16(name); wchar_t *str_w = ConvertFromUtf8ToUtf16(str); printf("UTF8 sequence/n"); for (i = 0; i < strlen(str); ++i) { printf("%02x ", (unsigned char)str[i]); } printf("/nUTF16 sequence/n"); for (i = 0; i < wcslen(str_w); ++i) { printf("%04x ", str_w[i]); } //Why not using printf or wprintf? Just because they do not working:) MessageBoxW(NULL, str_w, name_w, MB_OK); free(name_w); free(str_w); } int main() { ShowUtf8LiteralString("English english_c", "Chinese (Traditional)"); ShowUtf8LiteralString("简体 s_chinese_c", "你好世界"); ShowUtf8LiteralString("繁体 t_chinese_c", "中国語 (繁体)"); ShowUtf8LiteralString("Korea korea_c", "중국어 (번체)"); ShowUtf8LiteralString("What? what_c", "Chinês (Tradicional)"); }



Lee los artículos. Primero, no quieres UTF-8. UTF-8 es solo una forma de representar personajes. Desea caracteres anchos (wchar_t). Usted los escribe como L "yourtextgoeshere". El tipo de ese literal es wchar_t *. Si tienes prisa, solo busca wprintf.


Quizás intente un experimento:

#pragma setlocale(".UTF-8")

o:

#pragma setlocale("english_england.UTF-8")


Sé que llego tarde a la fiesta, pero creo que necesito extender esto . Para Visual C ++ 2005 y posteriores, si el archivo fuente no contiene BOM (marca de orden de bytes) y la configuración regional de su sistema no es inglés, VC asumirá que su archivo fuente no está en Unicode.

Para obtener los archivos fuente UTF-8 compilados correctamente, debe guardar en UTF-8 sin codificación BOM , y la configuración regional del sistema (idioma no Unicode) debe ser inglés .


Si bien es probable que sea mejor usar cadenas anchas y luego convertir según sea necesario a UTF-8. Creo que lo mejor es que, como lo mencionaste, uses escapes hexagonales en las cuerdas. Como supongamos que quería el punto de código /uC911 , podría hacer esto.

const char *str = "/xEC/xA4/x91";

Creo que esto funcionará bien, simplemente no es muy legible, así que si haces esto, por favor coméntalo para explicarlo.


Tuve un problema similar compilando literales de cadena estrecha (char) UTF-8 y lo que descubrí es que básicamente tenía que tener una BOM UTF-8 y #pragma execution_character_set("utf-8") [1], o ninguno de los BOM ni el pragma [2]. Usar uno sin el otro resultó en una conversión incorrecta.

Documenté los detalles en https://github.com/jay/compiler_string_test

[1]: Visual Studio 2012 no es compatible con execution_character_set. Visual Studio 2010 y 2015 funciona bien, y como saben con el parche en 2008 funciona bien.

[2]: Algunos comentarios en este hilo han notado que el uso de la BOM y el pragma puede dar como resultado una conversión incorrecta para los desarrolladores que usan una página de códigos local que es multibyte (por ejemplo, Japón).


Tuve un problema similar, la solución fue guardar en UTF8 sin auge utilizando opciones avanzadas de guardado


Tuve un problema similar. Mis literales de cadena UTF-8 se convirtieron a la página de códigos del sistema actual durante la compilación: acabo de abrir archivos .obj en un visor hexadecimal y ya estaban destrozados. Por ejemplo, el carácter ć era solo un byte.

La solución para mí fue guardar en UTF-8 y SIN BOM. Así es como engañé al compilador. Ahora cree que es solo una fuente normal y no traduce cadenas. En los archivos .obj, ahora hay dos bytes.

Haga caso omiso de algunos comentaristas, por favor. Entiendo lo que quiere, también quiero lo mismo: fuente UTF-8, archivos generados UTF-8, archivos de entrada UTF-8, UTF-8 sobre líneas de comunicación sin traducir.

Tal vez esto ayude ...


Una conversión portátil de cualquier codificación nativa que tenga es simple usando char_traits :: widen ().

#include <locale> #include <string> #include <vector> ///////////////////////////////////////////////////////// // NativeToUtf16 - Convert a string from the native // encoding to Unicode UTF-16 // Parameters: // sNative (in): Input String // Returns: Converted string ///////////////////////////////////////////////////////// std::wstring NativeToUtf16(const std::string &sNative) { std::locale locNative; // The UTF-16 will never be longer than the input string std::vector<wchar_t> vUtf16(1+sNative.length()); // convert std::use_facet< std::ctype<wchar_t> >(locNative).widen( sNative.c_str(), sNative.c_str()+sNative.length(), &vUtf16[0]); return std::wstring(vUtf16.begin(), vUtf16.end()); }

En teoría, el viaje de regreso, desde UTF-16 a UTF-8 debería ser similarmente fácil, pero descubrí que las configuraciones regionales UTF-8 no funcionan correctamente en mi sistema (VC10 Express en Win7).

Por lo tanto, escribí un convertidor simple basado en RFC 3629.

///////////////////////////////////////////////////////// // Utf16ToUtf8 - Convert a character from UTF-16 // encoding to UTF-8. // NB: Does not handle Surrogate pairs. // Does not test for badly formed // UTF-16 // Parameters: // chUtf16 (in): Input char // Returns: UTF-8 version as a string ///////////////////////////////////////////////////////// std::string Utf16ToUtf8(wchar_t chUtf16) { // From RFC 3629 // 0000 0000-0000 007F 0xxxxxxx // 0000 0080-0000 07FF 110xxxxx 10xxxxxx // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx // max output length is 3 bytes (plus one for Nul) unsigned char szUtf8[4] = ""; if (chUtf16 < 0x80) { szUtf8[0] = static_cast<unsigned char>(chUtf16); } else if (chUtf16 < 0x7FF) { szUtf8[0] = static_cast<unsigned char>(0xC0 | ((chUtf16>>6)&0x1F)); szUtf8[1] = static_cast<unsigned char>(0x80 | (chUtf16&0x3F)); } else { szUtf8[0] = static_cast<unsigned char>(0xE0 | ((chUtf16>>12)&0xF)); szUtf8[1] = static_cast<unsigned char>(0x80 | ((chUtf16>>6)&0x3F)); szUtf8[2] = static_cast<unsigned char>(0x80 | (chUtf16&0x3F)); } return reinterpret_cast<char *>(szUtf8); } ///////////////////////////////////////////////////////// // Utf16ToUtf8 - Convert a string from UTF-16 encoding // to UTF-8 // Parameters: // sNative (in): Input String // Returns: Converted string ///////////////////////////////////////////////////////// std::string Utf16ToUtf8(const std::wstring &sUtf16) { std::string sUtf8; std::wstring::const_iterator itr; for (itr=sUtf16.begin(); itr!=sUtf16.end(); ++itr) sUtf8 += Utf16ToUtf8(*itr); return sUtf8; }

Creo que esto debería funcionar en cualquier plataforma, pero no he podido probarlo, excepto en mi propio sistema, por lo que puede haber errores.

#include <iostream> #include <fstream> int main() { const char szTest[] = "Das tausendschöne Jungfräulein,/n" "Das tausendschöne Herzelein,/n" "Wollte Gott, wollte Gott,/n" "ich wär'' heute bei ihr!/n"; std::wstring sUtf16 = NativeToUtf16(szTest); std::string sUtf8 = Utf16ToUtf8(sUtf16); std::ofstream ofs("test.txt"); if (ofs) ofs << sUtf8; return 0; }