0

For example if I have the number as 390000 it would need to be printed as 390 000. If I have the number as 1200000 it would be printed as 1 200 000 etc.

Initially I thought about assigning the long long int to a string, and then writing if statements for each possible string length as there's only 11 possible lengths but this just seems really cumbersome and unnecessary.

Is there an easier way to do it?

LoztInSpace
  • 5,584
  • 1
  • 15
  • 27
  • 1
    What do you get if you take `a%1000`? – Kittsil May 23 '16 at 04:10
  • 2
    Keep storing `number%1000`. And then reverse it and display. – abhishek_naik May 23 '16 at 04:11
  • 2
    And btw, your representation of 12000000 is wrong. – abhishek_naik May 23 '16 at 04:11
  • A `long long int` must be at least 64-bits according to the spec, so that's 19 digits, and maybe a minus sign, or 20 digits if it's an `unsigned long long int`. Writing the number into a string is a good idea, but then use a loop to output the digits and spaces. All you have to do is figure out where the first gap should be. After that, gaps are every third digit. – user3386109 May 23 '16 at 05:45
  • Without scrolling down, any answer not including a call to [`localeconv()`](http://en.cppreference.com/w/c/locale/lconv) is incomplete. Different locales, different separator characters for thousands. Also note that [`thousands_sep` and `mon_thousands_sep` are two different things.](http://en.cppreference.com/w/c/locale/lconv) – DevSolar May 23 '16 at 14:10
  • @DevSolar disagree with "any answer not including a call to localeconv() is incomplete" concerning thousands separators. Thousands separators are only needed when printing numbers greater in magnitude of 999. A [solution](http://stackoverflow.com/a/37393204/2410359) need not print such large numbers at once. – chux - Reinstate Monica May 23 '16 at 14:24
  • @chux: The point being, the OP wants to separate thousands. The standard provides a (comparatively easy) way to honor the user's locale choice regarding the separator character. – DevSolar May 23 '16 at 14:27
  • @DevSolar True that OP can use `localeconv()` to discern a separator character. Yet that is a secondary issue of OP's post as OP all ready has a separator, a space, `' '` and needs a way to use it. Unfortunately standard C does not provide a standard C function to use the separator - hence the post. – chux - Reinstate Monica May 23 '16 at 14:37

6 Answers6

1

If you're on a POSIX system and one of your locales uses the space as digit grouping symbol, use the apostrophe (') in printf() conversion specifier.

setlocale(LC_NUMERIC, "SOMETHING");
printf("%'d", 345678); // 345 678

See a previous answer of mine to the question "convert astronomically large numbers into human readable form in C/C++"

Community
  • 1
  • 1
pmg
  • 106,608
  • 13
  • 126
  • 198
  • Hmmm.... good point on `'` in POSIX `printf()`, but shouldn't the locale to be used by the program be decided by the user (via appropriate environment variables), instead of being set by the program? – DevSolar May 23 '16 at 14:11
  • @DevSolar Use `setlocale(LC_NUMERIC, NULL)` (or `setlocale(LC_ALL, NULL)`) to [query the current global locale setting](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setlocale.html) or `setlocale(LC_NUMERIC, "")` – pmg May 23 '16 at 14:18
0

You can do it fairly easily by starting with a buffer sufficient in size to store the full long long number (and separators), and then using pointer arithmetic to insert a separator every 3rd number. For example, where MAXN is 32, you can do something like:

/** separate long long value every 3rd char into 's' */
char *sepnumber (char *s, long long val)
{
    char numstr[MAXN] = "";
    char *p = s + MAXN - 2;
    size_t idx = 0, len = 0;

    len = sprintf (numstr, "%lld", val);

    while (len--) {
        if (idx++ == 3) {
            idx = 1;
            *p-- = ' ';
        }
        *p = numstr[len];
        if (len) p--;
    }
    for (idx = 0; *p; p++, idx++) s[idx] = *p; /* copy to s */
    s[idx] = *p;    /* nul-terminate */

    return s;
}

A quick example would be:

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

#define MAXN 32

char *sepnumber (char *s, long long val);

int main (int argc, char **argv) {

    long long int lv = argc > 1 ? strtoll (argv[1], NULL, 10) : 1931583282;
    char fmtnum[MAXN] = "";

    printf (" %lld  =>  %s\n", lv, sepnumber (fmtnum, lv));

    return 0;
}

/** separate long long value every 3rd char into 's' */
char *sepnumber (char *s, long long val)
{
    char numstr[MAXN] = "";
    char *p = s + MAXN - 2;
    size_t idx = 0, len = 0;

    len = sprintf (numstr, "%lld", val);

    while (len--) {
        if (idx++ == 3) {
            idx = 1;
            *p-- = ' ';
        }
        *p = numstr[len];
        if (len) p--;
    }
    for (idx = 0; *p; p++, idx++) s[idx] = *p; /* copy to s */
    s[idx] = *p;    /* nul-terminate */

    return s;
}

Example Use/Output

$ ./bin/sepnum
 1931583282  =>  1 931 583 282

$ ./bin/sepnum 2212
 2212  =>  2 212
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

Another way using a Duff's Device:

#include <stdio.h>

static char *sep(char *str, long long value)
{
    char tmp[32];
    char *p = tmp;
    char *q = str;
    int len;

    len = snprintf(tmp, sizeof tmp, "%lld", value);
    if (*p == '-') { // Support for negatives
        *q++ = *p++;
        len--;
    }
    /*
     * Consider 5 mod 3
     * len % 3 is evaluated only once. E.g. 5 % 3 = 2
     * jumps into the middle of the loop (in this case to "case 2:")
     * case 2 and case 1 are evaluated
     * loops until NUL is reached evaluating all cases
     */
    switch (len % 3) do {
        *q++ = ' ';
        case 0: *q++ = *p++;
        case 2: *q++ = *p++;
        case 1: *q++ = *p++;
    } while (*p);
    *q = '\0';
    return str;
}

int main(void)
{
    char str[32];

    printf("%s\n", sep(str, 1200000));
    return 0;
}

Output

1 200 000
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

Here is a simple version without any nonsense. There are probably more efficient ways still, but if so, they do not include string handling or float numbers.

#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

static void print_number (uint32_t n)
{
  static bool remove_zeroes = true;

  if(remove_zeroes)
  {
    remove_zeroes = false;
    printf("%" PRIu32 " ", n);
  }
  else
  {
    printf("%.3" PRIu32 " ", n);
  }
}


void print_number_with_spaces (uint32_t n)
{
  bool remove_zeroes = true;

  while(n > 1000)
  {
    uint32_t tmp = n;
    uint32_t subtract = 1;

    while(tmp > 1000)
    {
      tmp /= 1000;
      subtract *= 1000;
    }

    print_number(tmp);

    if(subtract >= 1000)
    {
      n -= tmp*subtract;
    }
  } 

  print_number(n);
}


int main(int argc, char* argv[]) 
{
  print_number_with_spaces(1200000);
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

An easy way to print with spaces separating the thousands places uses recursion. Works for negative values too.

void print_1000(long long x) {
  long long msgroups = x / 1000;
  int lsgroup = x % 1000;
  if (msgroups) {
    print_1000(msgroups);
    char separator = ' ';  // adjust as deisred
    printf("%c%03d", separator, abs(lsgroup));
  } else {
    printf("%d", lsgroup);
  }
}

Sample usage

int main(void) {
  print_1000(0); puts("");
  print_1000(-1); puts("");
  print_1000(LLONG_MAX); puts("");
  print_1000(LLONG_MIN); puts("");
  return 0;
}

Output

0
-1
9 223 372 036 854 775 807
-9 223 372 036 854 775 808
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
-3

A quick solution I came up with is:

output = []
number = '1209873'
aux = reversed(list(number))
counter = 0
for digit in aux:
    output.append(digit)
    counter += 1
    if counter % 3 == 0:
        output.append(' ')

spaced_number = reduce(lambda x, y: x + y, reversed(output))

But I'm sure there are more efficient ways to solve your problem. ;)

  • 4
    This *looks a lot* like `Python` (albeit you can define plenty macros with `C`). But the OP asks for `C` solution, I think. – Ian May 23 '16 at 04:26