cprintfdigits

Entire log function


I've a little problem with a function that calculates the entire part of the logartihm of an integer. It's a detail in my case but I'd like to understand it ;)

As you see be testing it, my code is just a bubblesort function and my problem is relative to the function called log_entier (because log 9 is here 2 instead of 1, what I don't understand...)

Note that the argument of log_entier is supposed to be > 0

Thanks a lot in advance !!!

Here's my code :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void echanger_elements(char *s, unsigned i1, unsigned i2)  //echange deux elements d'une chaine dont on donne les indices
{
  char element = s[i1];
  s[i1] = s[i2];
  s[i2] = element;
}

int log_entier(int n)
{
  int log = -1;
  for (; n; n/=10)
    log++;
  return log;
}

char *print_digits(char n)
{
  char *s;
  s = malloc((3 - log_entier(n))*sizeof(char));
  int i;
  for (i = 3 - log_entier(n); i; i--)
  {
    s[i - 1] = ' ';
  }
  return s;
}



void bubblesort(char *s)  //trie une chaine de caractères en fonction de l'ordre de la table ascii
{
  int i;
  char plus_grand_el;
  char sorting;
  unsigned etape = 1;
  unsigned permutations = 0;
  while(1)
  {
    plus_grand_el = 0;
    sorting = 0;
    for (i = 1; i < strlen(s); i++)
    {
      if (s[i] < s[plus_grand_el])
      {
        sorting = 1;
        echanger_elements(s, i, plus_grand_el);
        permutations++;
      }
      plus_grand_el++;
    }
    printf(" Étape %s %d :   %s\n", print_digits(etape), etape++, s);
    if (sorting == 0)
    {
      printf(" ***La chaîne a été triée à l'aide de %d!***\n", permutations);
      break;
    }
  }
}


int main()
{
  char chaine[] = "ZZTHelXlo56456Wordl1265";
  bubblesort(chaine);
}

I would expect something like this :


 Étape     1 :   ZTHZeXll56456Woodl1265r
 Étape     2 :   THZZXel56456Wlodl1265or
 Étape     3 :   HTZXZe56456Wlldl1265oor
 Étape     4 :   HTXZZ56456Weldl1265loor
 Étape     5 :   HTXZ56456WZedl1265lloor
 Étape     6 :   HTX56456WZZde1265llloor
 Étape     7 :   HT56456WXZZd1265ellloor
 Étape     8 :   H56456TWXZZ1265dellloor
 Étape     9 :   56456HTWXZ1265Zdellloor
 Étape    10 :   54566HTWX1265ZZdellloor
 Étape    11 :   45566HTW1265XZZdellloor
 Étape    12 :   45566HT1265WXZZdellloor
 Étape    13 :   45566H1265TWXZZdellloor
 Étape    14 :   455661265HTWXZZdellloor
 Étape    15 :   455612656HTWXZZdellloor
 Étape    16 :   455126566HTWXZZdellloor
 Étape    17 :   451255666HTWXZZdellloor
 Étape    18 :   412555666HTWXZZdellloor
 Étape    19 :   124555666HTWXZZdellloor
 Étape    20 :   124555666HTWXZZdellloor
 ***La chaîne a été triée à l'aide de 142!***

instead of

 Étape     1 :   ZTHZeXll56456Woodl1265r
 Étape     2 :   THZZXel56456Wlodl1265or
 Étape     3 :   HTZXZe56456Wlldl1265oor
 Étape     4 :   HTXZZ56456Weldl1265loor
 Étape     5 :   HTXZ56456WZedl1265lloor
 Étape     6 :   HTX56456WZZde1265llloor
 Étape     7 :   HT56456WXZZd1265ellloor
 Étape     8 :   H56456TWXZZ1265dellloor
 Étape    9 :   56456HTWXZ1265Zdellloor
 Étape    10 :   54566HTWX1265ZZdellloor
 Étape    11 :   45566HTW1265XZZdellloor
 Étape    12 :   45566HT1265WXZZdellloor
 Étape    13 :   45566H1265TWXZZdellloor
 Étape    14 :   455661265HTWXZZdellloor
 Étape    15 :   455612656HTWXZZdellloor
 Étape    16 :   455126566HTWXZZdellloor
 Étape    17 :   451255666HTWXZZdellloor
 Étape    18 :   412555666HTWXZZdellloor
 Étape    19 :   124555666HTWXZZdellloor
 Étape    20 :   124555666HTWXZZdellloor
 ***La chaîne a été triée à l'aide de 142!***


Solution

  • When testing out your program, I noted that the compiler issued a warning about the fact that you were attempting to combine the printing of information and incrementing your "etape" counter together.

    /home/craig/C_Programs/Console/Log/main.c|55|warning: operation on ‘etape’ may be undefined [-Wsequence-point]|
    

    This warning referenced your print statement.

        printf(" Stage %s %d :   %s\n", print_digits(etape), etape++, s);
    

    Usually warnings are indicative of possible undefined behavior. With that, I also experienced the offset of the ninth line in the output.

    craig@Vera:~/C_Programs/Console/Log/bin/Release$ ./Log 
     Stage     1 :   ZTHZeXll56456Woodl1265r
     Stage     2 :   THZZXel56456Wlodl1265or
     Stage     3 :   HTZXZe56456Wlldl1265oor
     Stage     4 :   HTXZZ56456Weldl1265loor
     Stage     5 :   HTXZ56456WZedl1265lloor
     Stage     6 :   HTX56456WZZde1265llloor
     Stage     7 :   HT56456WXZZd1265ellloor
     Stage     8 :   H56456TWXZZ1265dellloor
     Stage    9 :   56456HTWXZ1265Zdellloor
     Stage    10 :   54566HTWX1265ZZdellloor
     Stage    11 :   45566HTW1265XZZdellloor
     Stage    12 :   45566HT1265WXZZdellloor
     Stage    13 :   45566H1265TWXZZdellloor
     Stage    14 :   455661265HTWXZZdellloor
     Stage    15 :   455612656HTWXZZdellloor
     Stage    16 :   455126566HTWXZZdellloor
     Stage    17 :   451255666HTWXZZdellloor
     Stage    18 :   412555666HTWXZZdellloor
     Stage    19 :   124555666HTWXZZdellloor
     Stage    20 :   124555666HTWXZZdellloor
     ***The string was sorted using 142!***
    

    Determining that what is desired is to print the stage and then increment the variable, following is the refactored code for that purpose.

        printf(" Stage %s %d :   %s\n", print_digits(etape), etape, s);
        etape++;
    

    When compiling this refactored code, the compiler no longer issued a warning about the incrementation of the variable. And following was the resulting test output.

    craig@Vera:~/C_Programs/Console/Log/bin/Release$ ./Log 
     Stage     1 :   ZTHZeXll56456Woodl1265r
     Stage     2 :   THZZXel56456Wlodl1265or
     Stage     3 :   HTZXZe56456Wlldl1265oor
     Stage     4 :   HTXZZ56456Weldl1265loor
     Stage     5 :   HTXZ56456WZedl1265lloor
     Stage     6 :   HTX56456WZZde1265llloor
     Stage     7 :   HT56456WXZZd1265ellloor
     Stage     8 :   H56456TWXZZ1265dellloor
     Stage     9 :   56456HTWXZ1265Zdellloor
     Stage    10 :   54566HTWX1265ZZdellloor
     Stage    11 :   45566HTW1265XZZdellloor
     Stage    12 :   45566HT1265WXZZdellloor
     Stage    13 :   45566H1265TWXZZdellloor
     Stage    14 :   455661265HTWXZZdellloor
     Stage    15 :   455612656HTWXZZdellloor
     Stage    16 :   455126566HTWXZZdellloor
     Stage    17 :   451255666HTWXZZdellloor
     Stage    18 :   412555666HTWXZZdellloor
     Stage    19 :   124555666HTWXZZdellloor
     Stage    20 :   124555666HTWXZZdellloor
     ***The string was sorted using 142!***
    

    The main takeaway here is to always review your compiler listing for any warnings that might point to undefined behavior. The "C" programming language does allow for combining and compacting operations; however, sometimes it is best to keep steps such as incrementing variables separate (and easier for any future code analysis).

    Use that as food for thought.