2012-03-31 18 views
8

Puede truncar cadenas con un especificador printf de campos de ancho:Especificando el ancho máximo de campo printf para números (truncando si es necesario)?

printf("%.5s", "abcdefgh"); 

> abcde 

Por desgracia, no funciona para los números (en sustitución de d con x es lo mismo):

printf("%2d", 1234); // for 34 
printf("%.2d", 1234); // for 34 
printf("%-2d", 1234); // for 12 
printf("%-.2d", 1234); // for 12 

> 1234 

¿Hay un fácil/forma trivial de especificar el número de dígitos que se imprimirán aunque signifique truncar un número?

MSDN específicamente says that it will not happen que parece innecesariamente limitante. (Sí, se puede hacer creando cadenas y cosas por el estilo, pero espero un “printf trick” o kludge inteligente.)

Respuesta

15

Al igual que muchas de mis mejores ideas, la respuesta vino a mí mientras estaba acostado, esperando a caerme dormido (no hay mucho más que hacer en ese momento que pensar).

Use modulus!

printf("%2d\n", 1234%10); // for 4 
printf("%2d\n", 1234%100); // for 34 

printf("%2x\n", 1234%16); // for 2 
printf("%2x\n", 1234%256); // for d2 

No es lo ideal, ya que no se puede truncar la izquierda (por ejemplo, en lugar de 1234), pero funciona para los principales casos de uso. Por ejemplo:

// print a decimal ruler 
for (int i=0; i<36; i++) 
    printf("%d", i%10); 
+1

Si desea truncar desde la izquierda, asumiendo los valores son números enteros, solo se dividen. Ejemplo: '1234/100 // for 12' –

+0

@ortang, sí, lo sé, pero es [no es lo mismo que truncar desde la derecha] (http://stackoverflow.com/questions/9953125/9957649?noredirect= 1 # comment34294951_22533677). – Synetech

3

Si desea truncar por la derecha puede convertir su número en una cadena y luego usar el ancho especificador campo de cadena.

"%.3s".format(1234567.toString) 
+1

Ya he reconocido que los convierte en cadenas; esta pregunta es sobre números brutos. Presumiblemente (alguien debería verificar para estar seguro, pero parece razonable), la conversión en 'printf' es más óptima que hacer una conversión manual. – Synetech

0

Usted podría utilizar snprintf para truncar por la derecha

char buf[10]; 
static const int WIDTH_INCL_NULL = 3; 

snprintf(buf, WIDTH_INCL_NULL, "%d", 1234); // buf will contain 12 
+0

Utiliza un búfer y valores codificados, por lo que es aún menos ideal, ya que usar memoria asignada dinámicamente sería aún peor. – Synetech

0

Por qué no de la izquierda? la única diferencia es el uso de una simple división:

printf("%2d", 1234/100); // you get 12 
+2

Cuando dije que mi solución no puede truncar desde la izquierda, no quise decir que no es posible; como demostraste, puedes usar la división. La razón por la que no lo uso es porque a diferencia del módulo que puede darle fácilmente los * n * dígitos * de * cualquier * más derecho, para truncar desde la izquierda, primero debe determinar el número de dígitos en el número anterior puedes dividir (en tu ejemplo, tienes que usar '1000' en lugar de' 100' si el número era '12345'). Esto crea mucho más trabajo para determinar primero el número de dígitos, luego multiplicar 10 para obtener una máscara, luego dividir, todo para truncar. ': - /' – Synetech

+0

Puede haber (probablemente) casos extremos en los que no estoy pensando, pero algo como 'num/pow (10, (int) log10 (num) - dígitos + 1);' debería funcionar para simple casos (asumiendo la base 10). –

0

Ejemplo de línea de comandos Bash:

localhost ~$ printf "%.3s\n" $(printf "%03d" 1234) 
123 
localhost ~$ 
Cuestiones relacionadas