Разделение разрядов при выводе числа

Си для меня иностранный язык, интуитивно попытался разделить число на разряды. (стандартной возможности это сделать или каких-то функций в стандартных библиотеках для этого не обнаружил)

Загадкой для меня остаётся, почему при первом вызове результат правильный, а при повторном какой-то мусор.

Каким образом поправить?

#include <stdio.h>
#include <locale.h>

char* intToStrWithThousandsSep(unsigned long long n)
{
  static int comma = '\0';
  static char retbuf[30];
  char *p = &retbuf[sizeof(retbuf) - 1];
  int i = 0;

  if (comma == '\0') {
    struct lconv *lcp = localeconv();
    if(lcp != NULL) {
      if(lcp->thousands_sep != NULL &&
         *lcp->thousands_sep != '\0')
        comma = *lcp->thousands_sep;
      else  
        comma = '.';
    }
  }

  *p = '\0';

  do {
    if(i%3 == 0 && i != 0)
      *--p = comma;
    *--p = '0' + n % 10;
    n /= 10;
    i++;
  } while(n != 0);

  return p;
}

int main() {
    int m;
    for(int i = 1; i < 11; i++){
      m = i * i * i * 1111111;    
      printf("%5d %16s %16s\n", i, intToStrWithThousandsSep(m), intToStrWithThousandsSep(m * 10));
    }  
    return 0;
}

Выполнить: https://onlinegdb.com/SJkiP1qCv


Ответы (1 шт):

Автор решения: Mikhailo

Чтобы убрать погрешность, описанную Harry, я переписал так:

char* intToStrWithThousandsSep(unsigned long long n, char * retbuf, int len)
{
    static int comma = '\0';
    char *p = &retbuf[len];

и

for(int i = 1; i < 11; i++){
    char buf1[50], buf2[50];
    m = i * i * i * 1111111;
    printf("%5d %12d %16s %26s\n", i, m,
           intToStrWithThousandsSep(m,buf1,50),
           intToStrWithThousandsSep(m * 10,buf2,50));
}

Теперь вывод при i < 6 cтал правильный. При i = 6 мы имеем m*10 равно 2399999760, что больше, чем влазит в int - отсюда вся ерунда во втором столбце при i >= 6.

От того, что ваша функция принимает unsigned long long, m не перестает быть обычным int.

→ Ссылка