0

Possible Duplicate:
Output 1000000 as 1,000,000 and so on

I have a float variable in the format xxxxxxxx.xx (Eg. 11526.99). I'd like to print it as 11,562.99 with a comma. How can I insert a comma in C?

Community
  • 1
  • 1
Jw123
  • 57
  • 2
  • 3
  • 8
  • 7
    @mvp: That's a C++ question, this question is tagged C. – dreamlax Jan 30 '13 at 04:46
  • AFAIK, there isn't a standard method in POSIX or the C standard that formats numbers without using a locale, yet you say that's what you'd like. You can find [`strfmon_l()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strfmon.html), but that takes a locale and is for formatting money. You can influence `fprintf()` et al if you set the locale. But I'm not aware of a general number formatter that isn't affected by a locale (which isn't to say there isn't one). – Jonathan Leffler Jan 30 '13 at 05:04
  • If you care to find a copy of Plauger's ["The Standard C Library"](http://www.amazon.com/Standard-C-Library-P-J-Plauger/dp/0131315099), it includes a function for formatting numbers as money or numbers according to a locale. It is for the C89 version of the locales, which are slightly simpler than the C99 or C11 version. (AFAIK, the C99 and C11 `setlocale()` and `localeconv()` functions are the same.) – Jonathan Leffler Jan 30 '13 at 05:08
  • You might find some useful information in [What are the formal and practical constraints on the values in `struct lconv` describing a locale](http://stackoverflow.com/questions/8261684/). I have some code that implements what is described there — contact me if you want it (see my profile). It is derived in part from Plauger's work, but amongst other changes works with C99. – Jonathan Leffler Jan 30 '13 at 05:17
  • 6
    Whoever marked this as a duplicate ***did not see that this is a C question and the duplicate is a C++ question***. – dreamlax Jan 30 '13 at 11:07
  • A better duplicate would be [How to format a number using comma as thousands separator in C?](https://stackoverflow.com/q/1449805/3744182). – dbc Jun 12 '22 at 01:14

2 Answers2

5

Try:

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

int main()
{
    float f = 12345.67;

    // obtain the existing locale name for numbers    
    char *oldLocale = setlocale(LC_NUMERIC, NULL);

    // inherit locale from environment
    setlocale(LC_NUMERIC, "");

    // print number
    printf("%'.2f\n", f);

    // set the locale back
    setlocale(LC_NUMERIC, oldLocale);
}

This depends on the current locale. The C and POSIX locales do not have a thousands separator. Instead of inheriting the locale from the environment you can set it yourself to a locale that you know uses a thousands separator. On my system, using "en_NZ" provides a thousands separator.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • I tried that. But the server on which I'm executing it doesn't have locales set and most importantly I'm not suppose to use locales for this. – Jw123 Jan 30 '13 at 04:46
  • 1
    @Jw123: You want to format a number in a locale-specific manner without using locales? – dreamlax Jan 30 '13 at 04:46
  • @Jw123: If I can ask, why can't you use locales, even temporarily (I've modified my code to show how to do this, if `LC_NUMERIC` is not set on your server then you can manually enter a locale name such as `"en_US"` or another that uses thousands seperators)? – dreamlax Jan 30 '13 at 05:11
0

The below addcommas function is a version locale-less, that allows negative floats (doesn't work with exponent like 3.14E10 though)

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

#define DOT     '.'
#define COMMA   ','
#define MAX     50

static char commas[MAX]; // Where the result is

char *addcommas(float f) {
  char tmp[MAX];            // temp area
  sprintf(tmp, "%f", f);    // refine %f if you need
  char *dot = strchr(tmp, DOT); // do we have a DOT?
  char *src,*dst; // source, dest

  if (dot) {            // Yes
    dst = commas+MAX-strlen(dot)-1; // set dest to allow the fractional part to fit
    strcpy(dst, dot);               // copy that part
    *dot = 0;       // 'cut' that frac part in tmp
    src = --dot;    // point to last non frac char in tmp
    dst--;          // point to previous 'free' char in dest
  }
  else {                // No
    src = tmp+strlen(tmp)-1;    // src is last char of our float string
    dst = commas+MAX-1;         // dst is last char of commas
  }

  int len = strlen(tmp);        // len is the mantissa size
  int cnt = 0;                  // char counter

  do {
    if ( *src<='9' && *src>='0' ) {  // add comma is we added 3 digits already
      if (cnt && !(cnt % 3)) *dst-- = COMMA;
      cnt++; // mantissa digit count increment
    }
    *dst-- = *src--;
  } while (--len);

  return dst+1; // return pointer to result
}

How to call it, for instance (main example)

int main () {

   printf ("%s\n", addcommas(0.31415));
   printf ("%s\n", addcommas(3.1415));
   printf ("%s\n", addcommas(31.415));
   printf ("%s\n", addcommas(314.15));
   printf ("%s\n", addcommas(3141.5));
   printf ("%s\n", addcommas(31415));
   printf ("%s\n", addcommas(-0.31415));
   printf ("%s\n", addcommas(-3.1415));
   printf ("%s\n", addcommas(-31.415));
   printf ("%s\n", addcommas(-314.15));
   printf ("%s\n", addcommas(-3141.5));
   printf ("%s\n", addcommas(-31415));
   printf ("%s\n", addcommas(0));

  return 0;
}

Compilation instruction example

gcc -Wall comma.c -o comma

Doing

./comma

Should output

0.314150
3.141500
31.415001
314.149994
3,141.500000
31,415.000000
-0.314150
-3.141500
-31.415001
-314.149994
-3,141.500000
-31,415.000000
0.000000
  • Set DOT to what is a dot
  • Set COMMA to what is supposed to be a comma
  • MAX set to 50 assumes the float converted as string will not be more than 49 characters (increase MAX in doubt)
  • Returns a pointer to the commas added string from the float given as parameter, pointer to a static area, thus
    • addcommas is not reentrant, and the value pointed to by the returned pointer (usually) changes after each call, eg.
    • in char *a = addcommas(3.1415) ; char *b = addcommas(2.7182) ; a cannot be used safely anymore after the second call to addcommas
Déjà vu
  • 28,223
  • 6
  • 72
  • 100
  • Thank you, ring0. That was helpful. I tried implemeting that and I got following error "conflicting types for ‘addcommas’" in the following line "char *addcommas(float f) {" – Jw123 Jan 30 '13 at 07:44
  • @Jw123 Sounds like you have managed to add a syntax error of your own making then. – Lundin Jan 30 '13 at 07:52
  • I guess there is no syntax error. I'm not sure what is going wrong. Other than that, I'm getting one more error -incompatible types when assigning to type ‘char *[MAX]’ from type ‘int’ when the addcommas function is called. I'm calling the function like this char* cost_comma[MAX]; cost_comma=addcommas(cost); cost is float variable. – Jw123 Jan 30 '13 at 08:00