Number of digits when using printf

1

My query is quite simple, but I can not find the answer. I need to specify the number of digits to be printed when I use printf with an integer.

Specifically, I always want to print 5 digits, regardless of whether my whole number has an amount greater or less than 5.

For example, if I have the number 123456, I want it to look like 12345. Now if I have the number 123, I want it to look 12300. (I do not need autocomplete with zeros at the beginning, but at the end)

I tried doing the following:

printf("%05i",numero); // Pero autocompleta con ceros al principio

I also tried:

printf("%5i",numero); // Pero ignora completamente ese 5 e imprime la cantidad total de digitos

Is there any other printf argument that solves this? Or should I create a function of my own?

Thank you!

    
asked by cventu 24.11.2016 в 22:31
source

3 answers

5

If you want to work with integers directly you can make a simple division:

numero = 123456;
printf("%i", numero/10); // Imprime 12345

And well, to add digits it would be enough to multiply by 10:

numero = 123;
printf("%i", numero*100); // Imprime 12300

It can also be done in a generic way:

int rectificarDigitos(int numero, int maxDigitos)
{
  int digitos = log10(numero) + 1;
  while( digitos > maxDigitos )
  {
    numero /= 10;
    digitos--;
  }

  while( digitos < maxDigitos )
  {
    numero *= 10;
    digitos++;
  }

  return numero; 
}

int main()
{
  int numero = rectificarDigitos(123456,5);
  printf("%i\n", numero);

  numero = rectificarDigitos(123,5);
  printf("%i\n", numero);
}

You could also convert the number to a text string and ignore the digits that do not interest you:

int numero = 123456;
char strNumero[10];
sprintf(strNumero,"%d",numero);
strNumero[5] = 0;
printf("%s",strNumero);

And, to top it off, we can make use of certain characteristics of printf :

void printNumero(int numero, int size)
{
  int digitos = log10(numero)+1;

  if( digitos < size )
  {
    printf("%d%0*d\n", numero, size-digitos, 0);
    //                  (1)       (2)       (3)
    // 1: "%d" -> numero a imprimir
    // 2: "%0*d" -> cantidad de que se repetira el numero al que precede
    // 3: "%0*d" -> numero a imprimir
  }
  else
  {
    if( digitos > size )
    {
      int div = pow(10,digitos-size);
      numero /= div;
    }

    printf("%d\n", numero);
  }
}

int main()
{
  printNumero(123456,5);
  printNumero(123,5);
}

EDIT:

Since you have clarified in your answer that you use a microcontroller, I propose a possible improvement of your function:

uint32_t integer_right_padding(uint32_t number, uint8_t desired_digits)
{
  uint8_t original_digits=0;

  for(uint32_t number_backup=number; number_backup != 0; original_digits++ )
  {
    number_backup/=10;
  }

  for( ; original_digits > desired_digits; original_digits-- )
    number /= 10;

  for( ; original_digits < desired_digits; original_digits++ )
    number *= 10;

  return number;
}

In what improvement?

  • The scope of the variables is reduced (any compiler compatible with C99 should admit as valid declare variables in a for )
  • You save a comparison in each iteration to adjust the number of digits.
  • The loop to adjust the number of digits makes fewer operations.

The function could be optimized even more, but if it is not essential I would choose to leave it that way since the code would start to be uglier.

    
answered by 25.11.2016 / 09:35
source
3

Print the number in a character buffer replenished with zeros and put the string completion character always in position 6 of the buffer:

char buffer[11] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0};
int escrito = snprintf(buffer, 10, "%d", numero);
buffer[escrito] = '0';
buffer[5] = 0;
printf("%s\n", buffer);

The buffer of the previous example has 11 characters since 10 are the maximum digits that an integer ( int ) * can have, the 11th character of the buffer is the end character of string (notice that it does not have quotes).

We print the number in the buffer, the function snprintf returns the number of characters written, so in the last written position we return to the character '0' (since snprintf will have written the character ending chain ).

Finally, in position 6 (where we want to always truncate the number) we put the chain ending character.

For example, suppose we want to show the numbers 42 and 101010:

 buffer         | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
snprintf 42     |'4'|'2'| 0 |'0'|'0'|'0'|'0'|'0'|'0'|'0'| 0 |
snprintf 101010 |'1'|'0'|'1'|'0'|'1'|'0'| 0 |'0'|'0'|'0'| 0 |

When printing 42, the position 2 of the buffer is marked as end of chain (with 0 ), the same happens with position 6 when printing 101010. Since in the first case we have written 2 characters and in the second 6, the buffer[escrito] = '0' instruction leaves us the buffer like this:

buffer | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
42     |'4'|'2'|'0'|'0'|'0'|'0'|'0'|'0'|'0'|'0'| 0 |
101010 |'1'|'0'|'1'|'0'|'1'|'0'|'0'|'0'|'0'|'0'| 0 |

If we showed the number at that moment we would see 4200000000 and 1010100000 respectively, so we use the instruction buffer[5] = 0; that leaves us this way the buffer:

buffer | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
42     |'4'|'2'|'0'|'0'|'0'| 0 |'0'|'0'|'0'|'0'| 0 |
101010 |'1'|'0'|'1'|'0'|'1'| 0 |'0'|'0'|'0'|'0'| 0 |

So showing the number at that moment we would see 42000 and 10101 respectively.

* In 32-bit architectures, the maximum number of an integer is (2 32 / 2) - 1 = 2,147,483,648

    
answered by 25.11.2016 в 09:30
2

I did not find any argument from printf to do what I was looking for so I created a function that deals with it. I share them with you if you are interested or need them in the future.

uint32_t integer_right_padding(uint32_t number, uint8_t desired_digits)
{
    uint8_t original_digits=0;
    uint32_t number_backup=number;
    uint8_t indexer=0;

    while ( number_backup >= 10)
    {
         number_backup/=10;
         original_digits++;
    }
    original_digits++;

    for (indexer=0 ; (indexer < (abs(desired_digits-original_digits))) ;     indexer++)
    {
        if (original_digits < desired_digits)
        {
            number*=10;
        }
        else
        {
            number/=10;
        }
    }

    return number;
}

The function receives two arguments, the first is the number that you want to auto-complete or cut and the second is the number of digits you want.

Examples:

integer_right_padding(123, 5); // Devuelve 12300
integer_right_padding(123456, 2); // Devuelve 12

and so on ... I hope it serves you!

    
answered by 25.11.2016 в 04:24