Después de consultar expertos en el tema, programadores de diversas ramas y profesores hemos dado con la solución al dilema y la compartimos en este post.
Solución:
Función localeconv()
simplemente lea la configuración de localización y ptrLocale->thousands_sep
en sí mismo no cambia esa configuración para la configuración regional actual.
EDITAR:
No sé cómo hacer esto en C, pero se pueden encontrar muchos ejemplos con salida en C++. Vea el siguiente ejemplo en C++:
#include
#include
using namespace std;
struct myseps : numpunct
// use ' as separator
char do_thousands_sep() const return ''';
// digits are grouped by 3
string do_grouping() const return "3";
;
int main()
cout.imbue(locale(locale(), new myseps));
cout << 1234567; // the result will be 1'234'567
EDITAR 2:
La referencia de C++ decía:
localeconv() devuelve un puntero a un objeto rellenado de tipo struct lconv. Los valores contenidos en el objeto se pueden sobrescribir mediante llamadas posteriores a localeconv y no modifican directamente el objeto. Las llamadas a setlocale con valores de categoría de LC_ALL, LC_MONETARY o LC_NUMERIC sobrescriben el contenido de la estructura.
Probé el siguiente ejemplo en MS Visual Studio 2012 (entiendo que es un estilo malo e inseguro):
#include
#include
#include
int main()
setlocale(LC_NUMERIC, "");
struct lconv *ptrLocale = localeconv();
strcpy(ptrLocale->decimal_point, ":");
strcpy(ptrLocale->thousands_sep, "'");
char str[20];
printf("%10.3lf n", 13000.26);
return 0;
y vi el resultado:
13000:260
por lo tanto, se puede suponer que los cambios de decimal_point
y thousands_sep
son posibles a través del puntero recibido con localeconv()
pero printf
ignora thousands_sep
.
EDITAR 3:
Ejemplo de C++ actualizado:
#include
#include
#include
using namespace std;
struct myseps : numpunct
// use ' as separator
char do_thousands_sep() const return ''';
// digits are grouped by 3
string do_grouping() const return "3";
;
int main()
stringstream ss;
ss.imbue(locale(locale(), new myseps));
ss << 1234567; // printing to string stream with formating
printf("%sn", ss.str().c_str()); // just output when ss.str() provide string, and c_str() converts it to char*
Hay un truco realmente muy sucio sobre cómo cambiar el carácter separador de mil por printf()
:
- Descargue la librería GNU.
- ejecutar el
configure --prefix=/usr/glibc-version
mando - correr
make -j 8
- obtenga el comando compilador muy largo con todos los interruptores del
make
producción - escribir el archivo fuente C
setMyThousandSeparator.c
- contenido ver abajo - compila este archivo fuente con los conmutadores gcc del punto 3.
- en su llamada de código fuente C normal
setMyThousandSeparator("'")
función antes de laprintf()
llamada. - Enlace
setMyThousandSeparator.o
con tu proyecto
Por el momento lo probé al vincular libc
static pero funciona.
Contenido de setMyThousandSeparator.c
:
#include
void setMyThousandSeparator(char * sMySeparator)
_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP) = sMySeparator;
Información:
Esta solución es segura para subprocesos porque accede a los mismos datos que printf()
¡lo hace!
Aquí hay una solución muy simple que funciona en cada distribución de Linux y no necesita, como mi primera respuesta, un glibc
cortar a tajos:
Todos estos pasos deben realizarse en el origenglibc
directorio- NO en el directorio de construcción - después de construir el glibc
version usando un directorio de compilación separado como se sugiere en estas instrucciones.
Mi nuevo locale
archivo se llama en_AT
.
- Crear en el
localedata/locales/
directorio de un archivo existenteen_US
un nuevo archivoen_AT
. - Cambiar todas las entradas para
thousands_sep
parathousands_sep "
o cualquier carácter que desee tener como separador de miles." - Cambie dentro del nuevo archivo todas las apariciones de
en_US
paraen_AT
. - Agregar al archivo
localedata/SUPPORTED
la línea:en_AT.UTF-8/UTF-8
. - correr en el construir directorio
make localedata/install-locales
. - El nuevo
locale
se añadirá automáticamente al sistema y se instantáneamente accesible para el programa.
En el programa C/C++, cambia al nuevo carácter separador de miles con:
setlocale( LC_ALL, "en_AT.UTF-8" );
usarlo con printf( "%'d", 1000000 );
que produce esta salida
1'000'000
Observación: Cuando necesite en el programa diferentes localizaciones que se determinan durante el tiempo de ejecución, puede usar este ejemplo de la man
paginas donde se carga lo solicitado locale
y simplemente reemplaza el LC_NUMERIC
ajustes de en_AT
.
Valoraciones y comentarios
Más adelante puedes encontrar las crónicas de otros administradores, tú igualmente puedes mostrar el tuyo si lo deseas.