Saltar al contenido

Establecer separador de miles para C printf

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():

  1. Descargue la librería GNU.
  2. ejecutar el configure --prefix=/usr/glibc-version mando
  3. correr make -j 8
  4. obtenga el comando compilador muy largo con todos los interruptores del make producción
  5. escribir el archivo fuente C setMyThousandSeparator.c - contenido ver abajo
  6. compila este archivo fuente con los conmutadores gcc del punto 3.
  7. en su llamada de código fuente C normal setMyThousandSeparator("'") función antes de la printf() llamada.
  8. 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.

  1. Crear en el localedata/locales/ directorio de un archivo existente en_US un nuevo archivo en_AT .
  2. Cambiar todas las entradas para thousands_sep para thousands_sep "" o cualquier carácter que desee tener como separador de miles.
  3. Cambie dentro del nuevo archivo todas las apariciones de en_US para en_AT.
  4. Agregar al archivo localedata/SUPPORTED la línea: en_AT.UTF-8/UTF-8 .
  5. correr en el construir directorio make localedata/install-locales.
  6. 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *